4

We have a table with a DATE column. How can we write a script which will return any weekend dates (Saturday or Sunday) over the next n years where we do NOT have the given weekend date in the table?

Marcus Leon
  • 55,199
  • 118
  • 297
  • 429

2 Answers2

6

To get all weekends between today and today + 365 days:

select as_of_date
from
(
  select
    rownum,
    sysdate + rownum - 1 as as_of_date
  from dual
  connect by rownum <= (sysdate+365) - sysdate
) sub
where to_char(as_of_date, 'DY', 'nls_date_language=AMERICAN') in ('SAT', 'SUN')

To exclude the dates that are present in a given table, just add "and not exists (select 1 from your_table y where y.the_date = as_of_date)" or similar, like that:

select as_of_date
from
(
  select
    rownum,
    sysdate + rownum - 1 as as_of_date
  from dual
  connect by rownum <= (sysdate+365) - sysdate
) sub
where to_char(as_of_date, 'DY', 'nls_date_language=AMERICAN') in ('SAT', 'SUN')
      and not exists (select 1 from my_table myt where myt.as_of_date = sub.as_of_date)

It can be simplified to not use a subquery, just change the occurrances of the "as_of_date" column to "sysdate + rownum - 1" and you should be good

It is also worth noting that I used that query when I needed to get all dates, and not only weekends. What I did in the answer was just exclude the weekends in the outer most query. If you don't want to return unneeded data, I'm sure the inner most query can be changed to not go through 365 days, but only through the number of weekends (i.e. use where rownum < 365/5 and retrieve date + (6,7) starting in a saturday or sunday), but I don't think this is a big performance issue so I didn't worry about that

beder
  • 1,086
  • 5
  • 10
  • 2
    Do all NLS settings have 1 and 7 as the weekend values? I referred to http://stackoverflow.com/questions/3450965/determine-if-oracle-date-is-on-a-weekend – Chetter Hummin Jan 10 '13 at 17:16
  • @ChetterHummin - you're right to pick this up. In Europe SAT and SUN are 6 and 7 respectively. In other pasrts of the worls they would be 1 nad 2 (but then not necessarily the "weekend"). – APC Jan 10 '13 at 17:27
  • 1
    it would be more stable as , `to_char(as_of_date, 'DY', 'nls_date_language=AMERICAN') in ('SAT', 'SUN')` – DazzaL Jan 10 '13 at 17:28
  • @ChetterHummin nice catch, edited the question with Dazzal's suggestion – beder Jan 10 '13 at 17:35
  • Might like to leap year-proof it with add_months(sysdate,12)-sysdate instead of (sysdate+365)-sysdate, which is of course just 365. – David Aldridge Jan 10 '13 at 20:17
1

These types of questions come up a lot. They generally involve creating a sequence of some sort and mapping it back.

Instead, if you can live with finding a missing date following by the number of missing dates in a row, then something like the following will work:

select t.date+7, (nextdowdate - t.date)/7 as nummissing
from (select t.date, lead(t.date) over (partition by to_char(t.date, 'Dy') order by date) as nextdowdate
      from t
      where to_char(t.date, 'Dy') in ('Sat', 'Sun')
     ) t
where nextdowdate - t.date > 7 and
      date between FirstDate and LastDate

This does assume that the first date is present and that the data extends beyond the last date. Basically, it is finding gaps between dates, then moving forward one week and counting the length of the gap.

Gordon Linoff
  • 1,242,037
  • 58
  • 646
  • 786
  • Thi ssolution side-steps the "is Sunday day 1 or 7?" problem. It is worth noting that the case of 'DAY' in the TO_CHAR() call governs the case of the output, so the case needs to match. – APC Jan 10 '13 at 17:30
  • The edit that set the language to American is amusing. The question is about Saturday and Sunday . . . not Samedi and Dimanche or Cumartesi and Pazar etc. I changed it back, just because changing it in one place didn't seem right. And, thank you @APC, I made the cases match. – Gordon Linoff Jan 10 '13 at 17:34
  • @gordon why? Firstly without fm, to_char returns Sunday as 'Sunday ' and second the nls is there so if a client connects with non English client, the query still works – DazzaL Jan 10 '13 at 17:41
  • @DazzaL . . . Internationalization is really good. The edited solution had two different ways of converting a date to day of week, which I think makes the solution more confusing. (The second is in the partition, and strictly speaking, internationalization is not an issue there.) – Gordon Linoff Jan 10 '13 at 17:48
  • 1
    @gordon fair enough (but the "amusing" suggested the edit was wrong). You still do need fmDay though or you won't ever match Saturday or Sunday as to_char (D, 'Day') would return space padded days. – DazzaL Jan 10 '13 at 18:09