MS SQL:如何从查找表中为每个外键对选择最新记录

时间:2018-09-07 10:44:01

标签: sql sql-server tsql

我有一个查找表,该表由两个外键组成一个唯一的对。每次进行交易时,表中都会重复这些唯一对,每次都会记录新的日期/时间。

我需要找到一种方法来仅返回每个外键对的“最新”记录,并能够通过WHERE语句对其应用其他过滤。

这是表格的示例:

PK     PartPK  LocationPK  TransactionDate          Bin
16473  1       1           2018-09-03 15:24:57.100  NULL
16472  1       1           2018-09-03 13:24:27.250  NULL
16471  1       1           2018-09-03 13:07:11.777  NULL
16470  1       1           2018-09-03 11:19:57.557  NULL
16469  1       2           2018-09-03 09:32:27.050  NULL
16468  2       1           2018-09-03 07:28:16.250  NULL
16467  2       1           2018-09-03 00:09:30.383  NULL
16466  2       1           2018-08-31 14:21:24.803  NULL
16465  2       1           2018-08-31 13:29:52.253  NULL
16463  3       1           2018-08-31 13:13:47.977  NULL

正确的查询应该能够给出以下结果:

PK     PartPK  LocationPK  TransactionDate          Bin
16473  1       1           2018-09-03 15:24:57.100  NULL
16469  1       2           2018-09-03 09:32:27.050  NULL
16468  2       1           2018-09-03 07:28:16.250  NULL
16463  3       1           2018-08-31 13:13:47.977  NULL

对于每个不同的PartPK和LocationPK配对,我只希望具有最大TransactionDate值的行。我还希望能够通过在查询中添加“ WHERE Bin is null”来进一步限制结果。

我该如何实现?

3 个答案:

答案 0 :(得分:3)

您可以使用row_number()函数:

select t.*
from (select t.*, row_number() over (partition by PartPK, LocationPK order by PK desc) as seq -- you can also order by TransactionDate
      from table t
     ) t
where seq = 1;

答案 1 :(得分:1)

SELECT Q2.* FROM (SELECT DISTINCT t.PartPK, t.LocationPK FROM Yourtab t) Q1
                CROSS APPLY 
                    (SELECT TOP 1 * FROM Yourtab t2 
                            WHERE t2.PartPK = Q1.PartPK AND t2.LocationPK = Q1.LocationPK 
                                ORDER BY TransactionDate DESC) Q2

答案 2 :(得分:1)

首先,我们应该简单地获取每个PK中最新的PartPK and LocationPK,然后将其用作子查询以返回该PK的完整记录,如下所示:

CREATE TABLE #test(PK INT, PartPK INT, LocationPK INT, TransactionDate DATETIME, Bin INT)
INSERT INTO #test VALUES
(16473,1,1,'2018-09-03 15:24:57.100',NULL),
(16472,1,1,'2018-09-03 13:24:27.250',NULL),
(16471,1,1,'2018-09-03 13:07:11.777',NULL),
(16470,1,1,'2018-09-03 11:19:57.557',NULL),
(16469,1,2,'2018-09-03 09:32:27.050',NULL),
(16468,2,1,'2018-09-03 07:28:16.250',NULL),
(16467,2,1,'2018-09-03 00:09:30.383',NULL),
(16466,2,1,'2018-08-31 14:21:24.803',NULL),
(16465,2,1,'2018-08-31 13:29:52.253',NULL),
(16463,3,1,'2018-08-31 13:13:47.977',NULL)

SELECT t.* 
FROM #test t
INNER JOIN (
            SELECT MAX(PK) AS PK --We can use `TransactionDate` as well
            FROM #test
            GROUP BY PartPK, LocationPK) t1 ON t.PK = t1.PK

输出

PK      PartPK  LocationPK  TransactionDate         Bin
16473   1       1           2018-09-03 15:24:57.100 NULL
16469   1       2           2018-09-03 09:32:27.050 NULL
16468   2       1           2018-09-03 07:28:16.250 NULL
16463   3       1           2018-08-31 13:13:47.977 NULL