具有最新记录的sql左联接

db2dz4w8  于 2021-07-29  发布在  Java
关注(0)|答案(3)|浏览(337)

我只想左键联接一个只有最新记录的表。我有 Customer1 表格:

+--------+----------+
| CustID | CustName |
+--------+----------+
|      1 | ABC123   |
|      2 | 456XYZ   |
|      3 | 5PQR3    |
|      4 | 789XYZ   |
|      5 | 789A     |
+--------+----------+
``` `SalesInvoice` 表格:

+------------+--------+-----------+
| InvDate | CustID | InvNumber |
+------------+--------+-----------+
| 2020-03-01 | 1 | IV236 |
| 2020-04-07 | 1 | IV644 |
| 2020-06-13 | 2 | IV869 |
| 2020-03-29 | 3 | IV436 |
| 2020-02-06 | 3 | IV126 |
+------------+--------+-----------+

我想要这个必要的输出:

+--------+------------+-----------+
| CustID | InvDate | InvNumber |
+--------+------------+-----------+
| 1 | 2020-04-07 | IV644 |
| 2 | 2020-06-13 | IV869 |
| 3 | 2020-03-29 | IV436 |
| 4 | | |
| 5 | | |
+--------+------------+-----------+

为了方便快捷,下面是示例代码。

drop table if exists #Customer1
create table #Customer1(CustID int, CustName varchar (100))
insert into #Customer1 values
(1,'ABC123'),
(2,'456XYZ'),
(3,'5PQR3'),
(4,'789XYZ'),
(5,'789A')

drop table if exists #SalesInvoice
create table #SalesInvoice(InvDate DATE, CustID INT, InvNumber varchar (100))
insert into #SalesInvoice values
('2020-03-01',1,'IV236'),
('2020-04-07',1,'IV644'),
('2020-06-13',2,'IV869'), 
('2020-03-29',3,'IV436'),
('2020-02-06',3,'IV126')
j2datikz

j2datikz1#

我喜欢用 TOP 1 WITH TIES 在这种情况下:

SELECT TOP 1 WITH TIES c.CustID, i.InvDate, i.InvNumber
FROM #Customer1 c
LEFT JOIN #Invoices i ON c.CustID = i.CustID
ORDER BY ROW_NUMBER() OVER (PARTITION BY c.CustID ORDER BY i.InvDate DESC);

演示

这里最重要的一个技巧是按行号订购,为每个客户分配一个序列,序列按发票日期递减。然后,这种方法只保留每个客户的最新发票记录。

bjp0bcyl

bjp0bcyl2#

我推荐 outer apply :

select c.*, i.*
from #c c outer apply
     (select top (1) i.*
      from #invoices i
      where i.custId = c.custId
      order by i.invDate desc
     ) i;
``` `outer apply` 实现一种特殊类型的 `join` 称为“横向连接”。这是一个非常强大的构造。但是当了解它们时,您可以将横向联接看作一个相关的子查询,它可以返回多个列和多个行。
nafvub8i

nafvub8i3#

您可以使用这个简单的自我解释的t-sql来尝试行数窗口函数,而不是横向联接

SELECT      c.CustID
            , d.InvDate
            , d.InvNumber
FROM        #C c
LEFT JOIN   (
            SELECT  *
                    , ROW_NUMBER() OVER (PARTITION BY CustID ORDER BY InvDate DESC) AS RowNo
            FROM    #D
            ) d
ON          c.CustID = d.CustID
            AND d.RowNo = 1

基本上,行号是用来过滤“最后”的发票在一个表扫描,而不是执行选择前1。。。order by在相关查询中必须执行多次--与客户数一样多。

相关问题