SQL左联接:选择一对多关系中的最后记录

SQL左联接:选择一对多关系中的最后记录,sql,join,greatest-n-per-group,advantage-database-server,Sql,Join,Greatest N Per Group,Advantage Database Server,我有一张客户表和一张明细表 我想为表中的每个客户提取一条记录,并在适用的情况下显示该客户的最新详细数据 目前我的where子句正在筛选出客户 我已经尝试将where子句移动到左侧外部联接中,但未能获得所需的结果 当我运行查询时,它似乎根本不会过滤产品 SELECT cust.Customer , cust.Company , inv.Date , inv.Product , inv.Units , inv.Extended FROM customerlist c

我有一张客户表和一张明细表

我想为表中的每个客户提取一条记录,并在适用的情况下显示该客户的最新详细数据

目前我的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
选择
客户
,客户公司
,投资日期
,库存产品
,存货单位
,投资扩展
从…起
定制客户
左外连接
详细信息
在…上
客户=库存客户
左外连接
详细信息inv2
在…上
inv.customer=inv2.customer
及(
库存日期<库存日期
或inv.date=inv2.date,inv.customer
我的问题类似于

我在尝试同样的事情,只是想包括每个客户和过滤器的产品

更新

样本数据

这是我的原始查询,非常好,只是我缺少客户

如果我删除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'
      )
左外连接
详细信息inv2
在…上
inv.customer=inv2.customer
及(
库存日期<库存日期
或inv.date=inv2.date,inv.customer
结果如下 显示的产品列不是“CC”等。。而且客户是重复的


您的第二次
左键加入
意味着在客户最近一次加入之前排除订单?我会重写它,因为
存在
。我不熟悉Advantage数据库,希望它的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支持
中的
,则可以通过将
X='A'或X='B'
替换为中的X来简化

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

请注意,如前所述,这表明客户的最新订单类型为“CC”、“CG”或“CH”。如果目标是显示客户该类型的最新订单,即使他们有另一类型的后续订单,也需要进行调整


例如,如果Bob购买了AB、BC、CC和DE,他将被排除在上述查询之外。如果你想包括他,因为他购买了CC产品,尽管他后来购买了DE,请发表评论,我将演示如何操作。

你的第二次
左加入是为了在客户最近的一次加入之前排除订单?我会重写它,因为
存在
。我不熟悉Advantage数据库,希望它的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支持
中的
,则可以通过将
X='A'或X='B'替换为中的X来简化

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

请注意,如前所述,这表明客户的最新订单类型为“CC”、“CG”或“CH”。如果目标是显示客户该类型的最新订单,即使他们有另一类型的后续订单,也需要进行调整


例如,如果Bob购买了AB、BC、CC和DE,他将被排除在上述查询之外。如果你想把他包括进来,因为他买了CC产品,尽管他后来买了DE,请评论,我会告诉你怎么做。

你几乎做对了

您的第一个查询将删除所有没有指定产品详细信息的客户,因为您没有在第一个
外部联接的
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

你几乎说对了

您的第一个查询将删除所有没有指定产品详细信息的客户,因为您没有在第一个
外部联接的
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

是否可以这样做:并且inv2.customer为空您使用的是什么RDM(Sql server、mysql、oracel)?您可以发布一些示例数据吗?Advantage DataBase server 9.1我的更新帮助与示例数据有关吗?如果有什么我可以做的,让它更清楚,让我知道。谢谢你的帮助!是否可以这样做:并且inv2.customer为空您使用的是什么RDM(Sql server、mysql、oracel)?您可以发布一些示例数据吗?Advantage DataBase server 9.1我的更新帮助与示例数据有关吗?如果有什么我可以做的,让它更清楚,让我知道。谢谢你的帮助!这并不能解决缺少客户的问题,Trevor希望结果中的每个客户都有行,即使是那些没有找到相应细节的客户,如果我理解正确的话。@JensMühlenhoff:嗯,你可能是对的。如果是这样的话,我不知道第二个
左连接的OP意味着什么。看起来你在正确的轨道上,希望你能让OP实现他的目标。你读过相关的问题了吗?OP似乎从接受的答案中选择了第二个
左连接
WHERE IS NULL
概念,但混淆了
ON
条件中的字段。这并不能解决缺少客户的问题,Trevor希望在结果中为每个客户指定行,即使是那些没有找到相应详细信息的客户,如果我理解正确的话。@JensMühlenhoff:嗯,你可能是对的。如果是这样的话,我不知道第二个
左连接的OP意味着什么。看起来你在正确的轨道上,希望你能让OP实现他的目标。你读过相关的问题了吗?OP似乎从接受的答案中选择了第二个
左连接
WHERE IS NULL
概念,但混淆了
ON
条件中的字段。观察良好