2012-10-23 19 views
5

Długi czas rozmówca, dzwoniący po raz pierwszy. Używam Crystal Reports 2010.Crystal Reports trzeba zgrupować według pochodnego zakresu dat

Mam codzienne informacje handlowe, które muszę zgrupować, jeśli wolumin się nie zmienia. Oto, jak wyglądają dane.

Trade # BegDate DataZakończenia Volume

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 

muszę to wyglądać tak.

Trade # DATERANGE Volume

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 

muszę grupie przez pochodzących zakresów dat, ale nie jestem pewien, jak to osiągnąć z Crystal. Jakieś pomysły??

+0

myślę, że kwestia ta jest podobna do http://stackoverflow.com/questions/13269569/drive-enddate-of -aktualny-rząd-od-stwardniały-od-następnego-wiersza/13418153 # 13418153 – WKordos

Odpowiedz

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 Błędne wyniki, słabe nazwy zmiennych. –

+0

działa, ale nie jest zrozumiały i dlatego nie można go replikować. +1 tylko dla twojego zainteresowania. – 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

Działa idealnie, wygląda jak minimum, które można kodować, aby wykonać zadanie. Wciąż szukam więcej rozwiązań. +1. – Rachcha

+0

Najlepsza i najbardziej kompaktowa odpowiedź, jaką mam. Dzięki! +50. – Rachcha

1

bym użyć funkcji „X-2” tłumienia, aby ukryć wszystkie oprócz ostatniego z każdego wiersza, jak i poprzedniego() i Next(), aby znaleźć punkty końcowe.

Grupowanie według BegDate; tłumienie szczegółów i grupowanie sekcji stopek.

Załóż {} function @UpdateCurrentBegDate gdzieś w nagłówku grupy

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 

a {} function @DisplayBegDate gdzie obecnie mają BegDate wyświetlanej

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

Przejdź do sekcji i Expert kliknij "X-2" obok opcji Suppress (dla sekcji nagłówka grupy). Jest to formuła nie

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

Jeśli trzeba zrobić sum lub innych obliczeń, należy to zrobić w {@UpdateCurrentBegDate} function (i że chcesz zmienić nazwę na {} lub @UpdateCurrentValues coś podobnego). Możesz również utworzyć nową funkcję, która sprawdza informacje Next(), jeśli chcesz zmienić tylko rzeczy, gdy grupa się zmieni - przy użyciu domyślnych funkcji sumowania będą zawierać ukryte wartości.

+0

Świetnie, nie widziałem "Potrzebuję czystego rozwiązania SQL", dopóki go nie zamieściłem. Nie usunę tego, ale odpowiada na oryginalne pytanie. – EvilBob22

+0

Dzięki za odpowiedź. Nawet ja go nie usunę. Mam pewne ograniczenia, które stworzyły potrzebę czystego rozwiązania SQL. Mam jeszcze spróbować przetestować odpowiedź Stevo. Zatrzymam twoje tutaj, jeśli ktoś potrzebuje takiego rozwiązania. +1 za Twoje zainteresowanie. Tymczasem prosimy, aby uzyskać rozwiązanie oparte wyłącznie na SQL.To wielka pomoc. – Rachcha

0

Jest to najbardziej eleganckie rozwiązanie mogłem wymyślić

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

Nie działa. Mam nazwę tabeli 'TRADE (TRADEID, BEGDATE, ENDDATE, VOLUME) z danymi opisanymi w pytaniu. Prosimy o dostarczenie rozwiązania, które będzie zgodne ze schematem i odpowiednio zredaguj odpowiedź. – Rachcha