【问题标题】:Join to only the "latest" record with t-sql使用 t-sql 仅加入“最新”记录
【发布时间】:2011-05-26 15:46:35
【问题描述】:

我有两张桌子。表“B”与表“A”是一对多的关系,这意味着表“A”中的一条记录将有表“B”中的许多记录。

表“B”中的记录主要通过日期来区分,我需要生成一个结果集,其中包含表“A”中的记录以及表“B”中的最新记录.出于说明目的,这里有一个示例架构:

Table A
-------
ID

Table B
-------
ID
TableAID
RowDate

我在制定查询以向我提供我正在寻找的任何帮助的结果集时遇到问题。

【问题讨论】:

  • 如果表B中的两行有相同的日期时间,你将如何定义单个最新记录?值得注意的是,DateTime 只能达到 3 毫秒(或类似的时间),而 DateTime2 可以测量到纳秒(因此更准确)。
  • 将[Table A] 与[Table B] 连接的列是TableAID?
  • 应该包括这个......你可以假设不会有重复的日期时间,所以总会有一个“最新的”:-)

标签: sql sql-server tsql join


【解决方案1】:
SELECT *
FROM tableA A
OUTER APPLY (SELECT TOP 1 * 
             FROM tableB B
             WHERE A.ID = B.TableAID
             ORDER BY B.RowDate DESC) as B

【讨论】:

  • 外部应用要快得多!
  • 与我在系统上尝试的其他方法相比,外部应用速度非常快。
  • 我刚刚测试了接受的答案与这个答案,我发现外部应用比接受的答案慢约 2 倍!
  • @Maderas 在测试期间你不止一次地运行了它们,对吧?否则,数据可能已被缓存。
  • @DanielLorenz 我不记得了。我通常每个运行至少 5 次。我也倾向于在测试新东西之前重新启动我的开发服务器以了解它的性能,但是......我不记得了。
【解决方案2】:
select a.*, bm.MaxRowDate
from (
    select TableAID, max(RowDate) as MaxRowDate
    from TableB
    group by TableAID
) bm
inner join TableA a on bm.TableAID = a.ID

如果您需要 TableB 中的更多列,请执行以下操作:

select a.*, b.* --use explicit columns rather than * here
from (
    select TableAID, max(RowDate) as MaxRowDate
    from TableB
    group by TableAID
) bm
inner join TableB b on bm.TableAID = b.TableAID
    and bm.MaxRowDate = b.RowDate
inner join TableA a on bm.TableAID = a.ID

【讨论】:

  • 这并不能完全回答这个问题,因为它只从表 b 中获取最大行日期。该问题已询问最近的行 - 因此需要为该行返回表 b 的其余部分,并且还需要考虑表 B 具有两个相同日期/时间的条目作为 TableA 参考
  • @Paul:我假设 TableB 只有 OP 指定的字段。已修改查询以处理您提到的情况。重复对于用户的数据来说可能是也可能不是问题。
  • 只是好奇......为什么要避免使用“*”?如果我真的想要结果集中的所有列,那么使用它有什么缺点?
  • @Joel:避免 * 解决了以下问题:重复列、关于返回列顺序的假设、选择比您需要的更多数据的性能损失等等。
【解决方案3】:
With ABDateMap AS (
    SELECT Max(RowDate) AS LastDate, TableAID FROM TableB GROUP BY TableAID
),
LatestBRow As (
    SELECT MAX(ID) AS ID, TableAID FROM ABDateMap INNER JOIN TableB ON b.TableAID=a.ID AND b.RowDate = LastDate GROUP BY TableAID
)
SELECT columns
FROM TableA a
INNER JOIN LatestBRow m ON m.TableAID=a.ID
INNER JOIN TableB b on b.ID = m.ID

【讨论】:

    【解决方案4】:

    表 B 连接是可选的:这取决于您是否需要其他列

    SELECT
        *
    FROM
        tableA A
        JOIN
        tableB B ON A.ID = B.TableAID
        JOIN
        (
        SELECT Max(RowDate) AS MaxRowDate, TableAID
        FROM tableB
        GROUP BY TableAID
        ) foo ON B.TableAID = foo.TableAID AND B.RowDate= foo.MaxRowDate
    

    【讨论】:

      【解决方案5】:

      只是为了清楚起见,并使那些偶然发现这个古老问题的人受益。如果Table B 中有重复的RowDate,则接受的答案将返回重复的行。更安全、更有效的方法是使用ROW_NUMBER()

      Select a.*, b.* -- Use explicit column list rather than * here
      From [Table A] a
      Inner Join ( -- Use Left Join if the records missing from Table B are still required
          Select *,
              ROW_NUMBER() OVER (PARTITION BY TableAID ORDER BY RowDate DESC) As _RowNum
          From [Table B]
      ) b
      On b.TableAID = a.ID
      Where b._RowNum = 1
      

      【讨论】:

        【解决方案6】:

        试试这个:

            BEGIN
        
        DECLARE @TB1 AS TABLE (ID INT, NAME VARCHAR(30) )
        DECLARE @TB2 AS TABLE (ID INT, ID_TB1 INT, PRICE DECIMAL(18,2))
        
        INSERT INTO @TB1 (ID, NAME) VALUES (1, 'PRODUCT X')
        INSERT INTO @TB1 (ID, NAME) VALUES (2, 'PRODUCT Y')
        
        INSERT INTO @TB2 (ID, ID_TB1, PRICE) VALUES (1, 1, 3.99)
        INSERT INTO @TB2 (ID, ID_TB1, PRICE) VALUES (2, 1, 4.99)
        INSERT INTO @TB2 (ID, ID_TB1, PRICE) VALUES (3, 1, 5.99)
        
        INSERT INTO @TB2 (ID, ID_TB1, PRICE) VALUES (1, 2, 0.99)
        INSERT INTO @TB2 (ID, ID_TB1, PRICE) VALUES (2, 2, 1.99)
        INSERT INTO @TB2 (ID, ID_TB1, PRICE) VALUES (3, 2, 2.99)
        
        
        SELECT A.ID, A.NAME, B.PRICE
          FROM @TB1 A
          INNER JOIN @TB2 B ON A.ID = B.ID_TB1 AND B.ID = (SELECT MAX(ID) FROM @TB2 WHERE ID_TB1 = A.ID)
        
        
        END
        

        【讨论】:

          【解决方案7】:

          这将使用 JOIN 获取最新记录。我认为这会对某人有所帮助

          SELECT cmp.*, lr_entry.lr_no FROM 
          (SELECT * FROM lr_entry ORDER BY id DESC LIMIT 1) 
          lr_entry JOIN companies as cmp ON cmp.id = lr_entry.company_id
          

          【讨论】:

            猜你喜欢
            • 2010-11-05
            • 2021-04-17
            • 1970-01-01
            • 2017-01-10
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2018-04-15
            相关资源
            最近更新 更多