2015-04-03 85 views
2

我有一個查詢,應從table1,其中兩個日期之間工作日的數量大於14返回記錄:如何在Oracle中處理1級深度嵌套限制?

select * 
from table1 
where (select count(*) 
     from (select rownum n 
      from table2 
      where rownum <= sysdate - table1.date_from + 1) 
     where to_char(table1.date_from + n - 1, 'D') <> 6 
     and to_char(table1.date_from + n - 1, 'D') <> 7 
     and not exists (select 1 
         from holidays 
         where table1.date_from + n - 1 between holiday_from and holiday_to)) > 14; 

第一次約會是從table1table1.date_from)選擇第二個日期爲sysdate。我需要檢查這幾天之間的所有日期,並排除星期六,星期日和節假日(從表holidays)。問題是部分:

(select rownum n 
from table2 
where rownum <= sysdate - table1.date_from + 1) 

,因爲我不能讓有table1.date_from(1級深度的限制)。我嘗試使用CONNECT BY:

select * 
    from table1 
    where (select count(*) 
      from dual 
      where to_char(table1.date_from + LEVEL - 1, 'D') <> 6 
      and to_char(table1.date_from + LEVEL - 1, 'D') <> 7 
      and not exists (select 1 
          from holidays 
          where table1.date_from + LEVEL - 1 between holiday_from and holiday_to) 
      CONNECT BY LEVEL <= sysdate - table1.date_from + 1) > 14; 

,但我不能在這裏使用LEVEL

and not exists (select 1 from holidays 
where table1.date_from + LEVEL - 1 between holiday_from and holiday_to) 

此外,我不能在過濾器中使用的功能,由於性能問題。那麼,解決這個問題的最佳解決方案是什麼?


UPDATE:

@imbalind:我真的很喜歡開始,並從SYSDATE降你的方法,我用它在我的解決方案。

@Lalit Kumar B:使用WITH子句解決了1級深度限制的問題。

我從你的答案相結合的提示,這是我的(工作)新的查詢:

select * 
from table1 
where (with counter as (select rownum n 
         from table2 
         where rownum <= 40) 
     select count(*) 
     from counter 
     where sysdate - n >= table1.date_from 
     and to_char(sysdate - n, 'D') <> DECODE('N', 'T', '-1', '6') 
     and to_char(sysdate - n, 'D') <> DECODE('N', 'T', '-1', '7') 
     and not exists (select 1 
         from holidays 
         where sysdate - n between holiday_from and holiday_to)) > 14; 

非常感謝你,我真的很感謝你的幫助。

+0

你可以把它的工作,才使嵌套子查詢的WITH子句擺脫SQL的限制。我使用了遞歸子查詢保理,請參閱我的答案。 – 2015-04-03 10:49:11

+0

感謝您的反饋並向我們展示最終實施。 – 2015-04-07 09:05:21

回答

1

,因爲我不能讓有table1.date_from(1級深度的限制)。我嘗試使用CONNECT BY:

你可以使用子查詢分解,即WITH子句避免子查詢的SQL限制。

嘗試此查詢,

SELECT * 
FROM table1 
WHERE (WITH required_dates(d) 
      AS (SELECT date_from + LEVEL - 1 
       FROM table1 
       CONNECT BY LEVEL < = (SYSDATE - date_from) + 1) 
     SELECT Count(*) 
     FROM required_dates 
     WHERE To_char(d, 'DY', 'NLS_DATE_LANGUAGE=ENGLISH') NOT IN ('SAT', 
       'SUN') 
       AND NOT EXISTS (SELECT 1 
           FROM holidays 
           WHERE table1.date_from + n - 1 BETWEEN 
             holiday_from AND holiday_to)) > 14 
2

我的方法是從sysdate -1降序開始生成固定數量的日期,然後對它們進行處理。在下面的片段中,我選擇了100. 一旦你獲得了正確的日期,就用它來過濾table1。

select dates 
    from (
    select rownum as rn, 
     dates 
    from (
    select x.dates, 
      nvl2(h.holiday_from,'T','F') as hd, 
      decode (to_char(x.dates,'D')-1,6,'T',7,'T','F') as WE 
     from (
     select trunc(sysdate) - rownum as dates 
     from dual d 
    connect By rownum <= 100 -- change this number if you plan on having long holidays 
      ) x 
    left outer join holidays h 
     on x.dates between h.holiday_fromand h.holiday_to 
     ) 
    where hd = 'F' and WE = 'F' -- exclude holidays and weekends 
     ) 
where rn = 14; -- return the 14th working day from now