TSQL-折叠匹配记录

TSQL-折叠匹配记录,sql,sql-server,sql-server-2012,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

代码:

查询:

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

目标:折叠键列上匹配的两行,并获得每个
案例
语句列的输出,而不是两个单独的列。注意,在real query中,这些表很大,我加入了其他几个表,并选择了更多的描述性列。此查询必须具有最小读取/快速!(即,如果可能,不能使用临时表/变量/CTE和全部)

您只需要一个聚合函数:

ID1 SD          ED
---------------------------
1   2016-09-01  2016-08-31
2   NULL        NULL
如果要避免
分组方式
,只要
@T2
中没有重复的行,就可以进行两次左联接:

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;

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

  • 后端执行查询所用的总时间
  • 最有效的查询样式。它将取决于您的其他表结构、数据需求、索引和数据大小 您需要使用PIVOT:

    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;
    

    无论如何,要避免GROUP BY/DISTINCT?假设@T2上没有重复项,您可以使用适当的条件进行两次左连接hanks!我曾想过使用2个左连接路由,但@t2是一个巨大的表,我不确定是否要这样做……除非这是最快的方法。@Lamak不需要子查询。可以将条件移动到on段。它会短得多。@Hamawi,我知道,但为了可读性,我更喜欢这样,优化器很可能会生成相同的执行计划“无法使用临时表/变量/CTE”。。。那么,你能用什么呢?您知道SQL Server可能会选择在后台构建临时表,即使您没有显式地这样做,对吗?除非要在同一数据库中执行
    选择进入
    ,否则将使用tempdb,并在执行过程中跨越进程边界。此外,请澄清您是希望汇总,还是仅仅表示所有组合-即,如果您有“2016-01-01”和“2016-01-02”的
    SD
    ,您是否希望同时看到这两种组合?
    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