2016-02-10 145 views
1

我有一張表,每週填充一次信息,並在表中填入單個列的日期。計算前一週

我就基本上從本週起對從上週專門的數據進行比較數據的查詢工作,所以我需要知道上週一週了。這很容易以下列方式完成:

WHERE TO_CHAR(LASTWEEK.DATE_GENERATED, 'IW') = TO_CHAR(SYSDATE, 'IW') -1 
    AND TO_CHAR(LASTWEEK.DATE_GENERATED, 'YY') = TO_CHAR(SYSDATE, 'YY') 

該表可能包含幾年的數據,因此我也檢查年份是否相同。

問題是當我們在今年的第一週,我們希望以比較前一週持平。這樣,我們在第1周減1,它給了我們0,但我希望它與從最後一年的第54周進行比較。

有沒有辦法做到這一點?

我覺得TRUNC功能可能與這方面的工作,但我不確定如何使用它在這種情況下,也同時要注意,它不應該與之比較的同一年,但去年。

提前致謝!

+1

只是爲了如果你使用IW,你應該使用IYYY(或者至少IY),否則你可能會得到奇怪的結果。2016-01-01是1653與YYIW和201653與YYYYIW ;但1553與IYIW和201553與IYYYW。(和1601 wi如果您願意,可以使用YYWW和201601;只是一致)。 –

回答

3

您可以用日期使用sysdate - 7一個星期前,比較,並與一個值組合:我使用的是IYYY年模型相匹配的IW一個

WHERE TO_CHAR(LASTWEEK.DATE_GENERATED, 'IYYYIW') = TO_CHAR(SYSDATE - 7, 'IYYYIW') 

通知,否則你」 d得到奇怪的結果。

但是正如@ditto所示,使用帶有IW格式掩碼的TRUNC更清潔。而@MaxU指出,截斷源列將阻止索引被使用,除非你有一個匹配的基於函數的索引。您可避免通過稍微修改同上的方法:

WHERE LASTWEEK.DATE_GENERATED >= TRUNC(SYSDATE - 7, 'IW') 
AND LASTWEEK.DATE_GENERATED < TRUNC(SYSDATE, 'IW'); 

作爲演示:

with lastweek(date_generated) as (
    select sysdate - level from dual connect by level <= 50 
) 
SELECT LASTWEEK.DATE_GENERATED 
FROM LASTWEEK 
WHERE LASTWEEK.DATE_GENERATED >= TRUNC(SYSDATE - 7, 'IW') 
AND LASTWEEK.DATE_GENERATED < TRUNC(SYSDATE, 'IW'); 

DATE_GENERATED 
-------------- 
2016-02-07  
2016-02-06  
2016-02-05  
2016-02-04  
2016-02-03  
2016-02-02  
2016-02-01  

還是看一年的變化,讓我們回到進一步,又只是作爲一個演示:

with lastweek(date_generated) as (
    select sysdate - level from dual connect by level <= 50 
) 
SELECT LASTWEEK.DATE_GENERATED 
FROM LASTWEEK 
WHERE LASTWEEK.DATE_GENERATED >= TRUNC(SYSDATE - 42, 'IW') 
AND LASTWEEK.DATE_GENERATED < TRUNC(SYSDATE - 35, 'IW'); 

DATE_GENERATED 
-------------- 
2016-01-03  
2016-01-02  
2016-01-01  
2015-12-31  
2015-12-30  
2015-12-29  
2015-12-28  
6

我會避免在此事件中使用TO_CHAR ...保持在DATE格式中...更安全,特別是在違反年限的情況下。

where trunc(LASTWEEK.DATE_GENERATED,'IW') = trunc(sysdate-7,'IW') 

這一個條件應該給你:)

你可以看到它在做什麼在這裏:

1 with w_data as (select sysdate-level d from dual connect by level <= 20) 
    2 select d, trunc(d, 'IW') w 
    3* from w_data 
    SQL>/

    D     W 
    -------------------- -------------------- 
    09-feb-2016 13:20:41 08-feb-2016 00:00:00 
    08-feb-2016 13:20:41 08-feb-2016 00:00:00 
    07-feb-2016 13:20:41 01-feb-2016 00:00:00 
    06-feb-2016 13:20:41 01-feb-2016 00:00:00 
    05-feb-2016 13:20:41 01-feb-2016 00:00:00 
    04-feb-2016 13:20:41 01-feb-2016 00:00:00 
    03-feb-2016 13:20:41 01-feb-2016 00:00:00 
    02-feb-2016 13:20:41 01-feb-2016 00:00:00 
    01-feb-2016 13:20:41 01-feb-2016 00:00:00 
    31-jan-2016 13:20:41 25-jan-2016 00:00:00 
    30-jan-2016 13:20:41 25-jan-2016 00:00:00 
    29-jan-2016 13:20:41 25-jan-2016 00:00:00 
    28-jan-2016 13:20:41 25-jan-2016 00:00:00 
    27-jan-2016 13:20:41 25-jan-2016 00:00:00 
    26-jan-2016 13:20:41 25-jan-2016 00:00:00 
    25-jan-2016 13:20:41 25-jan-2016 00:00:00 
    24-jan-2016 13:20:41 18-jan-2016 00:00:00 
    23-jan-2016 13:20:41 18-jan-2016 00:00:00 
    22-jan-2016 13:20:41 18-jan-2016 00:00:00 
    21-jan-2016 13:20:41 18-jan-2016 00:00:00 

    20 rows selected. 
1

從同上查詢將工作,但它不會在「過去一週使用索引。DATE_GENERATED」一欄,因爲應用功能(TRUNC)的,所以我會去爲以下幾點:

select 
    next_day(to_date('2016-01-10','yyyy-mm-dd')-14, 'MONDAY'), 
    next_day(to_date('2016-01-10','yyyy-mm-dd')-14, 'SUNDAY') 
from dual; 

輸出:

12/28/2015  01/03/2016 

所以,你的查詢將是:

WHERE LASTWEEK.DATE_GENERATED 
between next_day(to_date('2016-01-10','yyyy-mm-dd')-14, 'MONDAY') 
and next_day(to_date('2016-01-10','yyyy-mm-dd')-14, 'SUNDAY') 
+1

有關索引的好處,但請記住,日期名稱必須位於當前會話的NLS_DATE_LANGUAGE中,這可能會使它比看起來更脆弱。如果'date_generated'的時間總是設置爲午夜,那麼在兩者之間使用也是安全的,否則將會錯過週日午夜之後的記錄。 –