日期范围创建中的问题

时间:2012-03-09 15:49:09

标签: sql-server stored-procedures date-range

我一直在创建日期范围,但在某些情况下会出现问题:

这就是我所拥有的: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和status的表(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的创建,因为根据'group by'句子,此代码无法区分具有在不同时间范围内出现两次的状态的customer_id

我无法弄清楚如何做到这一点......

1 个答案:

答案 0 :(得分:0)

试试这个。希望它现在有效。

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