TSQL - 折叠匹配的记录

时间:2016-09-01 19:39:04

标签: sql sql-server sql-server-2012

代码:

DECLARE @T1 TABLE (ID1 INT);
DECLARE @T2 TABLE (ID1 INT, ID2 INT, DT DATE);

INSERT INTO @T1 (ID1)
VALUES (1), (2);

INSERT INTO @T2 (ID1, ID2, DT)
    SELECT 1, 100, GETDATE()
    UNION
    SELECT 1, 200, GETDATE() - 1
    UNION
    SELECT 3, 300, GETDATE()
    UNION
    SELECT 4, 200, GETDATE();

查询:

SELECT  
    T1.ID1,
    CASE 
       WHEN T2.ID2 = 100 THEN T2.DT
    END SD,
    CASE 
       WHEN T2.ID2 = 200 THEN T2.DT
    END ED
FROM
    @T1 T1
LEFT JOIN 
    @T2 T2 ON T1.ID1 = T2.ID1 AND T2.ID2 IN (100, 200);

当前输出:

ID1 SD          ED
----------------------------
1   2016-09-01  NULL
1   NULL        2016-08-31
2   NULL        NULL

期望的输出:

ID1 SD          ED
---------------------------
1   2016-09-01  2016-08-31
2   NULL        NULL

GOAL :折叠在键列上匹配的两行,并为每个CASE语句列而不是2个单独的列输出输出。请注意,在实际查询中,这些表很大,我加入了一些其他表并选择了更多描述性列。此查询必须具有最小读数/快速! (即,如果可能的话,不能使用临时表/变量/ CTE)

3 个答案:

答案 0 :(得分:2)

您只需要一个聚合函数:

SELECT  T1.ID1 ,
        MIN(CASE WHEN T2.ID2 = 100 THEN T2.DT
        END) SD ,
        MIN(CASE WHEN T2.ID2 = 200 THEN T2.DT
        END) ED
FROM    @T1 T1
        LEFT JOIN @T2 T2 ON T1.ID1 = T2.ID1
                            AND T2.ID2 IN ( 100, 200 )
GROUP BY T1.ID1;

如果您想避免GROUP BY,只要@T2中没有重复的行,您就可以进行2次左连接:

SELECT  T1.ID1 ,
        T100.DT SD,
        T200.DT ED
FROM    @T1 T1
LEFT JOIN ( SELECT *
            FROM @T2
            WHERE ID2 = 100) T100
    ON T1.ID1 = T100.ID1
LEFT JOIN ( SELECT *
            FROM @T2
            WHERE ID2 = 200) T200
    ON T1.ID1 = T200.ID1;

答案 1 :(得分:1)

你需要使用PIVOT:

Select * from
(SELECT  
    T1.ID1, T2.DT, 
    CASE 
       WHEN T2.ID2 = 100 THEN 'SD'
       WHEN T2.ID2 = 200 THEN 'ED'
    END SDED
FROM
    @T1 T1
LEFT JOIN 
    @T2 T2 ON T1.ID1 = T2.ID1 AND T2.ID2 IN (100, 200)) t
Pivot (MAX(DT) FOR SDED in ([SD], [ED]) ) P

答案 2 :(得分:0)

您的表格设计将决定实现目标的查询方式。因为,你选择了group by,其他选项肯定会涉及自我表连接和各种其他选项。最佳解决方案应基于以下内容:

  1. 后端执行查询所花费的总时间。
  2. 最佳效果的查询样式。它取决于您的其他表结构,您的数据需求,索引,数据大小。