2012-10-23 103 views
5

長時間的列表器,首次調用者。我正在使用Crystal Reports 2010.水晶報表需要根據派生日期範圍進行分組

我每天都有交易信息,如果交易量沒有變化,我需要將它們組合在一起。這是數據的樣子。

貿易#BegDate結束日期卷

1  1/1/2012 1/2/2012 500 
1  1/2/2012 1/3/2012 500 
1  1/3/2012 1/4/2012 1000 
1  1/4/2012 1/5/2012 750 
1  1/5/2012 1/6/2012 750 
1  1/6/2012 1/7/2012 500 
1  1/7/2012 1/8/2012 500 
1  1/8/2012 1/9/2012 500 

我需要它看起來像這樣。

貿易#DATERANGE卷

1  1/1/2012 - 1/3/2012 500 
1  1/3/2012 - 1/4/2012 1000 
1  1/4/2012 - 1/6/2012 750 
1  1/6/2012 - 1/9/2012 500 

我需要組由派生日期範圍,但我不知道如何與水晶做到這一點。有任何想法嗎??

+0

我覺得這個問題類似於 http://stackoverflow.com/questions/13269569/drive-enddate-of - 下一行的當前行/ 13418153#13418153 – WKordos

回答

0
with w as (
    select 1 id, to_date('1/1/2012', 'mm/dd/yyyy') db, to_date('1/2/2012', 'mm/dd/yyyy') de, 500 s from dual 
    union all 
    select 1, to_date('1/2/2012', 'mm/dd/yyyy'), to_date('1/3/2012', 'mm/dd/yyyy'), 500 from dual 
    union all 
    select 1, to_date('1/3/2012', 'mm/dd/yyyy'), to_date('1/4/2012', 'mm/dd/yyyy'), 1000 from dual 
    union all 
    select 1, to_date('1/4/2012', 'mm/dd/yyyy'), to_date('1/5/2012', 'mm/dd/yyyy'), 750 from dual 
    union all 
    select 1, to_date('1/5/2012', 'mm/dd/yyyy'), to_date('1/6/2012', 'mm/dd/yyyy'), 750 from dual 
    union all 
    select 1, to_date('1/6/2012', 'mm/dd/yyyy'), to_date('1/7/2012', 'mm/dd/yyyy'), 500 from dual 
    union all 
    select 1, to_date('1/7/2012', 'mm/dd/yyyy'), to_date('1/8/2012', 'mm/dd/yyyy'), 500 from dual 
    union all 
    select 1, to_date('1/8/2012', 'mm/dd/yyyy'), to_date('1/9/2012', 'mm/dd/yyyy'), 510 from dual  
    ) 

select tmin.db, tmax.de, tmin.s 
from 
(  
    select 
     row_number() over (order by db) id, 
      db, 
      s 
    from 
    ( 
     select 
      db, 
      s, 
      case 
        when ps is null 
         then 1 
        when ps != s 
         then row_number() over (order by db) 
       else 0 end num 
     from (

      select 
        (db) 
        , (de) 
        , lag (s,1) over (ORDER BY db) ps     
        , s 


      from w 
      ) t 
) t1 
    where num != 0 
) tmin, 

(select 
    row_number() over (order by db) id, 
     de, 
     s 
from 
(  
    select 
      db, 
      de, 

      s, 
      case 
       when ps is null 
        then 1 
       when ps != s 
        then row_number() over (order by de desc) 
      else 0 end num 
    from (

     select 
        db 
       ,(de) 
       , lag (s,1) over (ORDER BY de desc) ps     
       , s     

     from w 
     order by db 
     ) t 
) t1 
where num != 0) tmax 

where tmin.id = tmax.id 
+0

-1結果錯誤,變量名稱不佳。 –

+0

有效,但無法理解,因此無法複製。 +1只是爲了您的興趣。 – Rachcha

4
with w as (
select 1 id, to_date('1/1/2012', 'mm/dd/yyyy') start_date, to_date('1/2/2012', 'mm/dd/yyyy') end_date, 500 sales_volume from dual 
union all 
select 1, to_date('1/2/2012', 'mm/dd/yyyy'), to_date('1/3/2012', 'mm/dd/yyyy'), 500 from dual 
union all 
select 1, to_date('1/3/2012', 'mm/dd/yyyy'), to_date('1/4/2012', 'mm/dd/yyyy'), 1000 from dual 
union all 
select 1, to_date('1/4/2012', 'mm/dd/yyyy'), to_date('1/5/2012', 'mm/dd/yyyy'), 750 from dual 
union all 
select 1, to_date('1/5/2012', 'mm/dd/yyyy'), to_date('1/6/2012', 'mm/dd/yyyy'), 750 from dual 
union all 
select 1, to_date('1/6/2012', 'mm/dd/yyyy'), to_date('1/7/2012', 'mm/dd/yyyy'), 500 from dual 
union all 
select 1, to_date('1/7/2012', 'mm/dd/yyyy'), to_date('1/8/2012', 'mm/dd/yyyy'), 500 from dual 
union all 
select 1, to_date('1/8/2012', 'mm/dd/yyyy'), to_date('1/9/2012', 'mm/dd/yyyy'), 500 from dual  
) 

,t as (select sales_volume 
      ,start_date 
      ,end_date 
      ,lag (sales_volume,1) over (order by start_date) prev_sales_volume 
     from w 
     order by start_date) 
,u as (select * 
     from t 
     where nvl(prev_sales_volume,-1) != sales_volume 
     order by start_date) 
select start_date 
     ,nvl(lead (start_date,1) over (order by start_date),(select max(end_date) from w)) end_date 
     ,sales_volume 
from u 
order by start_date 
+0

完美的工作,看起來像最小的人可以編碼完成工作。仍在尋找更多的解決方案。 +1。 – Rachcha

+0

我得到的最好和最簡潔的答案。謝謝! +50。 – Rachcha

1

我會使用「X-2」抑制功能隱藏所有,但最後的每一行,和上一個()和Next()來查找端點。

Group by BeDDate;抑制細節和組頁腳部分。

在組頭

WhilePrintingRecords;  
Global DateVar CurrentBegDate; 

If PreviousIsNull({table.Volume}) or Previous({table.Volume}) <> {table.Volume} 
    Then (//We found a new range 
     CurrentBegDate = {table.BegDate}; 
    ); 

""; //Display nothing on screen 

及{} @DisplayBegDate功能,你目前已經被BegDate顯示

EvaluateAfter({@UpdateCurrentBegDate}); 
Global DateVar CurrentBegDate; 

轉到節專家創建{} @UpdateCurrentBegDate某處功能和單擊Suppress選項旁邊的「X-2」(針對組標題部分)。這是公式有

Not(NextIsNull({table.Volume}) or Next({table.Volume}) <> {table.Volume}) 

如果你需要做的總計或其它計算,你會做它在{} @UpdateCurrentBegDate功能(和你想要的名稱更改爲{} @UpdateCurrentValues或相似的東西)。你也可以創建一個新的函數來檢查Next()信息,如果你只想在組改變的時候改變它的話 - 使用默認的總和函數將包括隱藏的值。

+0

太好了,我沒有看到「我需要一個純粹的SQL解決方案」,直到發佈之後。我不會刪除它,它回答了原來的問題。 – EvilBob22

+0

感謝您的回答。即使我不會刪除它。我對創建純SQL解決方案的需求有一些限制。我還沒有嘗試測試Stevo的答案。如果有人需要像這樣的解決方案,我會保持在這裏。 +1爲您的興趣。 同時,請注意您只能獲得基於SQL的解決方案。這將有很大的幫助。 – Rachcha

0

這是最優雅的解決方案,我能想出

WITH DirectTrades(tradeid, SourceDate, EndDate, Volume, Row, KillRow, Depth) AS 
(
    SELECT tradeid 
      BegDate AS SourceDate, 
      EndDate, 
      Volume, 
      ROW_NUMBER() over (partition by Table# order by BegDate) AS Row, 
      ROW_NUMBER() over (partition by Table# order by BegDate) AS KillRow, 
      0 AS Depth 
    FROM Trade 
    UNION ALL 
    SELECT t1.Tradeid 
      dt.SourceDate, 
      t1.EndDate, 
      t1.Volume, 
      dt.Row, 
      dt.Row + dt.Depth + 1, 
      dt.Depth + 1 
    FROM Trade AS t1 
      INNER JOIN 
      DirectTrades AS dt ON 
        t1.BegDate=dt.EndDate AND 
        t1.Volume=dt.Volume AND 
        t1.tradeid=dt.Tradeid 
) 

SELECT dt1.Tradeid 
     dt1.SourceDate, 
     dt1.EndDate, 
     dt1.Volume 
FROM DirectTrades dt1 
     INNER JOIN 
     (
     SELECT dt2.Row, 
       MAX(dt2.KillRow) AS KillRow 
     FROM DirectTrades dt2 
     WHERE dt2.Row NOT IN 
       (
       SELECT dt3.KillRow 
       FROM DirectTrades dt3 
       WHERE dt3.Depth <> 0 
       ) 
     GROUP BY dt2.Row 
     ) dt4 ON dt1.Row=dt4.Row AND dt1.KillRow=dt4.KillRow 
ORDER BY SourceDate 
+0

不起作用。我的表格名稱爲TRADE(TRADEID,BEGDATE,ENDDATE,VOLUME),其中包含問題中所述的數據。請提供符合架構的解決方案並相應地編輯您的答案。 – Rachcha