проблема в создании диапазона дат - PullRequest
0 голосов
/ 09 марта 2012

Я создаю диапазон дат, но в некоторых случаях возникает проблема:

Вот что у меня есть: TABLE_1

date          customer_id      status      total
----         -------------    --------    -------
20120201         1                a         10
20120202         1                a         20
20120203         1                b         20
20120204         1                b         20
20120205         1                a         20
20120206         1                a         20
20120201         2                d         30
20120202         2                e         40

После выполнения моей процедуры у меня есть это: TABLE_2

customer_id      status      start_date       end_date
-------------    --------    -----------      ---------
     1              a         20120201        NULL
     1              b         20120203        20120131
     2              d         20120201        20120201
     2              e         20120202        NULL

Но это то, что я хочу, таблица с диапазонами дат, основанными на customer_id и статусе (end_date представляет регистр с самой последней датой): TABLE_3

customer_id      status      start_date       end_date
-------------    --------    -----------      ---------
     1              a         20120201        20120202
     1              b         20120203        20120204
     1              a         20120205        NULL
     2              d         20120201        20120201
     2              e         20120202        NULL

Моя процедура хранения выглядит следующим образом:

;WITH TEMP AS (
SELECT
    Date
    customer_id
    status
FROM table_1
GROUP BY
    date,
    customer_id,
    status
)
,TEMP2 AS (
  SELECT 
        ID  = ROW_NUMBER() OVER(PARTITION BY customer_id ORDER BY MAX(date) DESC),
        start_date  = MIN(date),
        end_date    = MAX(date),
        [customer_id],
        [status]
  FROM TEMP 
  GROUP BY 
        [customer_id],
        [status]
)
SELECT 
  A.customer_id,
  A.status,
  A.start_date,
  end_date      = DATEADD(DAY,-1,B.start_date)
FROM TEMP2 A
LEFT JOIN TEMP2 B
    ON A.customer_id = B.customer_id
    AND A.ID = B.ID + 1

Я знаю, что моя ошибка в создании CTE TEMP2, потому что этот код не может различать для customer_id со статусом с двумя вхождениями в разных диапазонах времени, основываясь на предложении 'group by'

Я не могу понять, как это сделать ...

1 Ответ

0 голосов
/ 13 марта 2012

Попробуй это. Надеюсь, что это работает сейчас.

DECLARE @table_1 TABLE ( 
    date DATETIME, 
    customer_id INT, 
    status CHAR(1), 
    total INT 
) 

INSERT @table_1 (date, customer_id, status, total) 
VALUES   
('20120201', 1, 'a', 10), 
('20120202', 1, 'a', 20),  
('20120203', 1, 'b', 20),  
('20120204', 1, 'b', 20),  
('20120205', 1, 'a', 20),  
('20120206', 1, 'a', 20),  
('20120201', 2, 'd', 30),  
('20120202', 2, 'e', 40) 



;WITH CTE_1 AS ( 
    SELECT  
        customer_id,  
        status, 
        date, 
        ROW_NUMBER() OVER(PARTITION BY customer_id ORDER BY date ASC) AS seq 
    FROM @table_1    
),
CTE_2 AS (
    SELECT  
        customer_id,  
        status, 
        date, 
        seq,
        1 AS flg,
        1 AS seq2
    FROM CTE_1 
    WHERE 
        seq = 1

    UNION ALL 

    SELECT  
        CTE_1.customer_id,  
        CTE_1.status, 
        CTE_1.date, 
        CTE_1.seq,
        CASE WHEN CTE_2.status = CTE_1.status THEN 0 ELSE 1 END,
        CASE WHEN CTE_2.status = CTE_1.status THEN CTE_2.seq2 ELSE CTE_2.seq2 + 1 END
    FROM CTE_1   
    INNER JOIN CTE_2
        ON CTE_1.customer_id = CTE_2.customer_id
            AND CTE_1.seq = CTE_2.seq + 1   
)
SELECT 
    st.customer_id, 
    st.status, 
    st.date AS start_date, 
    DATEADD(DAY, -1, en.date) AS end_date  
FROM CTE_2 AS st
LEFT JOIN CTE_2 AS en
    ON st.customer_id = en.customer_id
        AND st.seq2 = en.seq2 - 1
        AND en.flg = 1
WHERE
    st.flg = 1
ORDER BY 
    st.customer_id,
    st.seq2
...