1

I have a customer table, and a detail table.

I want to want to pull a record for every customer in the table and show the latest detail data on that customer where applicable.

Currently my where clause is filtering out customers.

I have tried moving the where clause into the left outer join, but I have not been able to get the desired result.

It does not seem to filter the product at all when I run the query.

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

My question is similar to

SQL join: selecting the last records in a one-to-many relationship

I'm trying for the same thing just want to include every customer and filter by product.

Update

Sample data

Here is my Original Query, which is great except for I am missing customers

Here is my original query

If I remove the where clause and insert it into the left join as follows

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'
      )

Here is the result There are product columns showing up that are not 'CC' etc.. And the customers are duplicated.

enter image description here

4

2 回答 2

3

你几乎是对的。

您的第一个查询删除了所有没有指定产品详细信息的客户,因为您没有在第ON一个条件中指定产品过滤器OUTER JOIN

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(如果表中有一个 id 字段detail)。

这是因为OR条件是通过主键过滤detail具有相同日期的记录。

更新

由于有问题的表没有主键字段,您可以使用ROWIDADS 功能来解决这个问题:

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
于 2013-06-13T09:46:40.550 回答
1

您的第二个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 支持,您可以通过替换X = 'A' OR X = 'B'为来简化。X IN ('A', 'B')IN


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

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

于 2013-06-12T23:00:02.787 回答