[英]SQL Left join: selecting the last records in a one-to-many relationship
我有一个客户表和一个详细信息表。
我想要为表中的每个客户提取记录,并在适用的情况下显示该客户的最新详细数据。
目前我的where子句正在筛选出客户。
我已经尝试将where子句移动到左外连接中,但是我无法获得所需的结果。
在运行查询时,它似乎根本不会过滤产品。
SELECT
cust.Customer
, cust.Company
, inv.Date
, inv.Product
, inv.Units
, inv.Extended
FROM
customerlist cust
LEFT OUTER JOIN
detail inv
ON
cust.customer = inv.customer
LEFT OUTER JOIN
detail inv2
ON
inv.customer = inv2.customer
AND (
inv.date < inv2.date
OR inv.date = inv2.date AND inv.customer < inv2.customer
)
WHERE
(
inv.Product = 'CC'
OR inv.Product = 'CG'
OR inv.Product = 'CH'
)
AND inv2.customer IS NULL
我的问题类似于
我正在尝试同样的事情,只想包括每个客户和按产品过滤。
更新
样本数据
这是我的原始查询,除了我缺少客户外,这是很好的
如果我删除where子句并将其插入左连接,如下所示
LEFT OUTER JOIN
detail inv2
ON
inv.customer = inv2.customer
AND (
inv.date < inv2.date
OR inv.date = inv2.date AND inv.customer < inv2.customer
)
AND (
inv.Product = 'CC'
OR inv.Product = 'CHECK'
OR inv.Product = 'ACH'
)
结果如下所示产品列不是“CC”等。客户是重复的。
你几乎是对的。
您的第一个查询将删除所有没有指定产品详细信息的客户,因为您没有在第一个OUTER JOIN
的ON
条件中指定产品过滤器。
SELECT
cust.Customer
, cust.Company
, inv.Date
, inv.Product
, inv.Units
, inv.Extended
FROM
customerlist cust
LEFT OUTER JOIN
detail inv
ON
cust.customer = inv.customer
AND inv.Product IN ('CC', 'CG', 'CH')
LEFT OUTER JOIN
detail inv2
ON
inv.customer = inv2.customer
AND (
inv.date < inv2.date
OR inv.date = inv2.date AND inv.customer < inv2.customer
)
WHERE
inv2.customer IS NULL
应该这样做。
还有一件事我觉得不太正确。 AND inv.customer < inv2.customer
部分应该是AND inv.id < inv2.id
(如果detail
表中有id字段)。
这是因为OR
条件是通过主键过滤具有相同日期的detail
记录。
UPDATE
由于有问题的表没有主键字段,您可以使用ROWID
ADS功能来解决:
SELECT
cust.Customer
, cust.Company
, inv.Date
, inv.Product
, inv.Units
, inv.Extended
FROM
customerlist cust
LEFT OUTER JOIN
detail inv
ON
cust.customer = inv.customer
AND inv.Product IN ('CC', 'CG', 'CH')
LEFT OUTER JOIN
detail inv2
ON
inv.customer = inv2.customer
AND (
inv.date < inv2.date
OR inv.date = inv2.date AND inv.ROWID < inv2.ROWID
)
WHERE
inv2.customer IS NULL
您的第二个LEFT JOIN
是为了在客户最近之前排除订单? 我将其重写为EXISTS
。 我不熟悉Advantage DataBase,希望它的SQL实现并不罕见。
SELECT
Cust.Customer,
Cust.Company,
Inv.Date,
Inv.Product,
Inv.Units,
Inv.Extended
FROM
customerlist AS Cust
LEFT JOIN detail AS Inv ON Cust.customer = Inv.customer
WHERE
(Inv.Product = 'CC' OR Inv.Product = 'CG' OR Inv.Product = 'CH')
AND NOT EXISTS (SELECT * FROM detail AS Inv2 WHERE Cust.customer = Inv2.customer AND Inv2.date > inv.date)
假设Advantage支持IN
,您可以通过将X = 'A' OR X = 'B'
替换为X IN ('A', 'B')
来简化。
请注意,如上所述,这表示客户的最新订单类型为“CC”,“CG”或“CH”。 如果目标是向客户显示该类型的最新订单,即使他们具有其他类型的后续订单,也需要进行调整。
例如,如果Bob已经购买了AB,BC,CC和DE,则他将被排除在上述查询之外。 如果你想包括他,因为他买了CC产品,虽然他后来买了DE,评论,我会说明如何。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.