2014-02-24 63 views
0

我有一個遞歸的SQL,我正在運行哪些工作,但給我以下警告。db2 supress遞歸警告

SQL0347W遞歸公用表表達式「DT_LAST_YEAR」可能包含無限循環 。 SQLSTATE = 01605

我該如何擺脫警告?

INSERT INTO REP_MAN_TRAN_COUNTS (SITEDIRECTORYID, BUSINESSDATE, TRANCOUNT) 
WITH dt_this_year (level, seqdate) AS 
( 
    SELECT 1, date(current timestamp) -7 DAYS FROM sysibm.sysdummy1 
    UNION ALL 
    SELECT level, seqdate + level days FROM dt_this_year WHERE level < 1000 AND seqdate + 1 days < date(current timestamp) 
) 
,dt_last_year (level, seqdate) AS 
( 
    SELECT 1, date(current timestamp) -7 DAYS - 1 year FROM sysibm.sysdummy1 
    UNION ALL 
    SELECT level, seqdate + level days FROM dt_last_year WHERE level < 1000 AND seqdate + 1 days < date(current timestamp) -1 year 
) 
select 10049, date(dts.calendarday), count(*) trancount 
from (
    SELECT seqdate AS calendarday FROM dt_this_year 
    UNION 
    SELECT seqdate AS calendarday FROM dt_last_year 
) dts LEFT JOIN ccftrxheader ccf 
ON date(dts.calendarday) = date(ccf.businessdate) 
WHERE ccf.sitedirectoryid=10049 
GROUP BY ccf.sitedirectoryid,dts.calendarday 

感謝您的幫助

回答

2

你如何擺脫警告?
通過更改代碼,使其不再生成警告。 隱藏警告是有問題的,因爲它通常掩蓋了一個潛在的更大的問題。我相當肯定它在這裏抱怨,因爲你爲level提供的終止條款永遠不可能達到(因爲你永遠不會操縱它)。

就個人而言,我可能會重新寫你的查詢弄成這個樣子:

INSERT INTO Rep_Man_Tran_Counts (siteDirectoryId, businessDate, tranCount) 

WITH dt_Calendar_Data (level, calendarDay) AS 
         (SELECT l, c 
         FROM (VALUES (1, CURRENT_DATE - 7 DAYS), 
            (1, CURRENT_DATE - 7 DAYS - 1 YEAR)) t(l, c) 
         UNION ALL 
         SELECT level + 1, calendarDay + 1 DAYS 
         FROM dt_Calendar_Data 
         WHERE level < 7) 
SELECT 10049, dtCal.calendarDay, COALESCE(COUNT(*), 0) as tranCount 
FROM dt_Calendar_Data dtCal 
LEFT JOIN ccftrxHeader ccf 
     ON ccf.businessDate = dtCal.calendarDay 
      AND ccf.siteDirectoryId = 10049 

GROUP BY dtCal.seqDate 

(未經測試,爲您提供無樣本數據,我沒有一個DB2實例)
我假設你實際上想要一個LEFT JOIN,而不是你實際得到的常規INNER JOIN(由於WHERE條款中的條件,也可能是GROUP BY)。爲了避免向數據添加空值,我已將計數包裝在COALESCE(...)中,這會給您0以代替。
我也假設businessDate是一個DATE類型,而不是一個時間戳。如果時間戳,則需要調整此查詢(請注意,您使用的函數將優化器忽略索引)。 請注意,日期的操作順序很重要!值得慶幸的是,在處理年份範圍時,您只需在格里曆(2月29日)擔憂一天。您當前的訂單將比較相同的日曆天數開始的範圍(哪一個具有「差距」取決於今年還是去年是閏年)。


編輯:

當然,讓我們來看看這CTE:

FROM(VALUES (1, CURRENT_DATE - 7 DAYS), 
      (1, CURRENT_DATE - 7 DAYS - 1 YEAR)) t(l, c) 

這只是作爲一個參考表標準VALUES條款。這是構建一個小臨時表的SQL標準方法(而不是引用虛擬表,這往往是供應商特定的)。如果語句上2014-02-26運行,那麼所得到的表將是:

t 
l c 
=============== 
1 "2014-02-19" 
1 "2013-02-19" 

這些列獲得通過CTE的列清單,然後將其在引用改名爲參加(和遞歸CTE的情況下,由遞歸部分)。
這就形成了起始數據的遞歸查詢的其餘部分:

UNION ALL 
SELECT level + 1, calendarDay + 1 DAYS 
FROM dt_Calendar_Data 
WHERE level < 7 

在DB2(和一些其他RDBMS),遞歸的CTE基本上執行迭代,作用關「前」調用的結果。每次,我們增加level,並增加一天到calendarDay。 「下一個」行然後:

level calendarDay 
====================== 
2  "2014-02-20" 
2  "2013-02-20" 

這樣繼續下去,直到「以前的」行有level = 7,這意味着一個新行不產生(檢查WHERE條款)。通常,最好只有一個終止條件(並且每次迭代都會取得進展),以便優化程序更容易發現。結果數據然後在範圍內:

level calendarDay 
===================== 
1  "2014-02-19" 
.  ..... 
7  "2014-02-26" 

1  "2013-02-19" 
.  ..... 
7  "2013-02-26" 

...作爲一個附註,我生成了今年/去年的數據,以縮短參考文獻的數量。如果你只需要一年,level是不必要的。

+0

哇..謝謝..那真是太棒了。我對你給我的東西做了一些輕微的修改,它的工作方式和我想要的完全一樣。對不起,你可以幫我一個忙,你在和條款裏寫了些什麼。我有麻煩了解遞歸如何工作。 – Richie

+0

@Richie - 這樣的事情? –