【问题标题】:LEFT Join on a Subquery with specific criteria在具有特定条件的子查询上左连接
【发布时间】:2021-11-11 15:07:24
【问题描述】:

我有两个要加入的表

table1
----------------------------
Id         Name         Num
123X       Apple        17

table2
-------------------------------------------------
id           EndDt         SomeVal      
123X         10/1/2021     xxx
123X         3/1/2022      yyy

我正在尝试从 table1 aLEFT JOIN table2 b on a.id = b.id 中进行选择 - 但是,我只想在 table2 中的 ID 上选择 MAX(EndDt)

Select a.*, b.SomeVal
from table1 a 
    LEFT OUTER JOIN table2 b on a.id=b.id // and b.MAX(EndDt)

这样的事情可行吗?

【问题讨论】:

  • 再添加几行样本数据,同时指定预期结果。

标签: sql sql-server join


【解决方案1】:

有几种方法可以做到这一点。不过,我对您的数据做了一些假设。

  1. LEFT JOIN 与子查询一起使用:
    SELECT T1.*,
           sq.SomeVal
    FROM dbo.Table1 T1
         LEFT JOIN (SELECT ROW_NUMBER() OVER (PARTITION BY t2.Id ORDER BY t2.EndDt DESC) AS RN,
                           t2.Id,
                           t2.SomeVal
                    FROM dbo.Table2 T2) sq ON T1.Id = T2.Id
                                          AND T2.RN = 1;
    
  2. 使用APPLYTOP
    SELECT T1.*,
           sq.SomeVal
    FROM dbo.Table1 T1
         OUTER APPLY (SELECT TOP (1)
                             t2.Id,
                             t2.SomeVal
                      FROM dbo.Table2 T2
                      WHERE T2.Id = T1.Id
                      ORDER BY T2.EndDt DESC) sq;
    
  3. 使用 CTE 并获取每组的“前 1”行:
    WITH CTE AS(
        SELECT T1.*,
               T2.SomeVal,
               ROW_NUMBER() OVER (PARTITION BY T1.ID ORDER BY T2.MaxDt DESC) AS RN
        FROM dbo.Table1 T1
             LEFT JOIN dbo.Table2 T2 ON T1.Id = T2.Id)
    SELECT *
    FROM CT
    WHERE RN = 1;
    
  4. 使用TOP (1) WITH TIES:
    SELECT TOP (1) WITH TIES
           T1.*,
           T2.SomeVal
    FROM dbo.Table1 T1
         LEFT JOIN dbo.Table2 T2 ON T1.Id = T2.Id
    ORDER BY ROW_NUMBER() OVER (PARTITION BY T1.ID ORDER BY T2.MaxDt DESC) ASC;
    

请注意,如果 ID 在表 Table1 中不是唯一的(因此我对您的数据做出假设),选项 3 和 4 将无法按预期工作。

【讨论】:

    【解决方案2】:

    我建议先使用窗口化的 ROW_NUMBER 函数获取最大值 table2,然后加入该子查询。

    ;WITH cte AS (
        SELECT *, [Row] = ROW_NUMBER() OVER (PARTITION BY b.Id ORDER BY b.EndDt DESC)
        FROM table2 b
    )
    SELECT a.*, cte.SomeVal
    FROM table1 a
    LEFT JOIN cte ON a.id = cte.id AND cte.[Row] = 1
    

    【讨论】:

      【解决方案3】:

      对于单个值,使用相关子查询:

      SELECT
          a.id,
          a.name,
          a.num,
          (
              SELECT TOP 1 SomeValue 
              FROM table2 As b 
              WHERE b.id = a.id 
              ORDER BY b.EndDt DESC
          ) As SomeVal
      FROM
          table1 a
      

      【讨论】:

        猜你喜欢
        • 2011-03-12
        • 2010-12-02
        • 2016-02-17
        • 2019-06-17
        • 1970-01-01
        • 2015-02-06
        • 1970-01-01
        • 2016-05-02
        • 2014-09-24
        相关资源
        最近更新 更多