我一直在创建日期范围,但在某些情况下会出现问题:
这就是我所拥有的: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
我无法弄清楚如何做到这一点......
答案 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