表T1
+----+------------+------------+--------+------+
| ID | Sdate | Edate | Reason | Type |
+----+------------+------------+--------+------+
| 1 | 5/30/2016 | | | A |
| 1 | 1/19/2016 | 12/15/2016 | USD | B |
| 1 | 11/20/2016 | 10/1/2016 | IT | B |
| 2 | 10/25/2016 | | | A |
| 2 | 9/22/2016 | 7/11/2016 | SD | B |
| 2 | 2/13/2016 | | | A |
| 2 | 1/1/2016 | 4/3/2016 | IT | B |
+----+------------+------------+--------+------+
对于每个ID,我需要为Type = A选择最小Sdate,为Type = B选择最大Edate,以及与Type = B关联的Discharge Reason。不仅仅有两种类型,但我已将A和B显示为一个例子
期望输出:
+-------------+-----------+------------+------------------+
| Customer ID | Startdate | Enddate | Discharge Reason |
+-------------+-----------+------------+------------------+
| 1 | 5/30/2016 | 12/15/2016 | USD |
| 2 | 2/13/2016 | 7/11/2016 | SD |
+-------------+-----------+------------+------------------+
尝试:
WITH CTE AS
(
SELECT
ID
,SDate
,EDate
,Reason
,Type
FROM T1
)
SELECT
CTE.ID AS [Customer ID]
,MIN(CASE WHEN CTE.Type='A' THEN CTE.SDate END)
OVER (PARTITION BY CTE.CID) AS StartDate
,CTE.EDate AS Enddate
,CTE.Reason AS [Discharge Reason]
FROM CTE
INNER JOIN (SELECT CTE.ID, MAX(CTE.EDate) AS EEDate
FROM CTE WHERE CTE.Type='B' GROUP BY CTE.ID) CTE2
ON CTE.ID=CTE2.ID AND CTE.Edate=CTE2.EEDAte
这给了我一个空白的Startdate列,因为外部联合相关子查询上的INNER JOIN用于获取Max Edate
和关联的Discharge Reason
,导致查询忽略{{1}因此没有开始。我如何将这些工作结合在一起?
答案 0 :(得分:1)
这是一个经典的top-n-per-group
问题,您需要做两次。
示例数据
DECLARE @T TABLE (ID int, Sdate date, Edate date, Reason varchar(50), Type char(1));
INSERT INTO @T (ID, Sdate, Edate, Reason, Type) VALUES
(1, '2016-05-30', NULL , NULL , 'A'),
(1, '2016-01-19', '2016-12-15' , 'USD', 'B'),
(1, '2016-11-20', '2016-10-01' , 'IT' , 'B'),
(2, '2016-10-25', NULL , NULL , 'A'),
(2, '2016-09-22', '2016-07-11' , 'SD' , 'B'),
(2, '2016-02-13', NULL , NULL , 'A'),
(2, '2016-01-01', '2016-04-03' , 'IT' , 'B');
对行进行两次编号。
PARTITION BY ID ORDER BY Type, Sdate
会为每个ID
和最小Sdate
以及Type=A
提供第1行。
PARTITION BY ID ORDER BY Type DESC, Edate DESC
会为每个ID
以及最大Edate
和Type=B
提供第1行。
SELECT
ID
,Sdate
,Edate
,Reason
,Type
,ROW_NUMBER() OVER (PARTITION BY ID ORDER BY Type, Sdate) AS rnA
,ROW_NUMBER() OVER (PARTITION BY ID ORDER BY Type DESC, Edate DESC) AS rnB
FROM @T
ORDER BY ID, Type, Sdate
;
中级结果
+----+------------+------------+--------+------+-----+-----+
| ID | Sdate | Edate | Reason | Type | rnA | rnB |
+----+------------+------------+--------+------+-----+-----+
| 1 | 2016-05-30 | NULL | NULL | A | 1 | 3 |
| 1 | 2016-01-19 | 2016-12-15 | USD | B | 2 | 1 |
| 1 | 2016-11-20 | 2016-10-01 | IT | B | 3 | 2 |
| 2 | 2016-02-13 | NULL | NULL | A | 1 | 3 |
| 2 | 2016-10-25 | NULL | NULL | A | 2 | 4 |
| 2 | 2016-01-01 | 2016-04-03 | IT | B | 3 | 2 |
| 2 | 2016-09-22 | 2016-07-11 | SD | B | 4 | 1 |
+----+------------+------------+--------+------+-----+-----+
现在,我们需要获取包含rnA=1
和rnB=1
的行,并将它们组合在一起ID
。
<强>查询强>
WITH
CTE
AS
(
SELECT
ID
,Sdate
,Edate
,Reason
,Type
,ROW_NUMBER() OVER (PARTITION BY ID ORDER BY Type, Sdate) AS rnA
,ROW_NUMBER() OVER (PARTITION BY ID ORDER BY Type DESC, Edate DESC) AS rnB
FROM @T
)
,CTE_A
AS
(
SELECT
ID
,Sdate
FROM CTE
WHERE rnA = 1
)
,CTE_B
AS
(
SELECT
ID
,Edate
,Reason
FROM CTE
WHERE rnB = 1
)
SELECT
CTE_A.ID
,CTE_A.Sdate
,CTE_B.Edate
,CTE_B.Reason
FROM
CTE_A
INNER JOIN CTE_B ON CTE_B.ID = CTE_A.ID
ORDER BY ID
;
<强>结果强>
+----+------------+------------+--------+
| ID | Sdate | Edate | Reason |
+----+------------+------------+--------+
| 1 | 2016-05-30 | 2016-12-15 | USD |
| 2 | 2016-02-13 | 2016-07-11 | SD |
+----+------------+------------+--------+
答案 1 :(得分:0)
你可以试试这个:
SELECT
t.ID
,t.SDate
,t.EDate
,Reason
FROM (
SELECT ID, MIN(CASE WHEN Type='A' THEN SDate END) as SDate , max(CASE WHEN Type='B' THEN EDate END ) as EDate
FROM T1
group by ID) t
INNER JOIN T1 on t.ID = T1.id and t.EDate = T1.Edate and type = 'B'
OR
WITH CTE AS
(
SELECT ID, MIN(CASE WHEN Type='A' THEN SDate END) as SDate , max(CASE WHEN Type='B' THEN EDate END ) as EDate
FROM T1
group by ID
)
SELECT
CTE.ID AS [Customer ID]
,CTE.SDate AS StartDate
,CTE.EDate AS Enddate
,T1.Reason AS [Discharge Reason]
FROM CTE
INNER JOIN T1
ON CTE.ID=T1.ID AND CTE.Edate=T1.EDAte and T1.type = 'B'
如果B类型没有重复的最大日期,如果有,则需要稍微调整一下。