2012-10-23 58 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