我有这个LEFT JOIN吗?

时间:2011-06-30 07:52:21

标签: sql ms-access join left-join outer-join

我需要找到在给定日期之后尚未订购的客户总数。

我有两张桌子:

| customers           |    // There's more to this but this is all
+----+------+---------+    // you need to answer this question
| ID | Name | Created |
+----+------+---------+

| orders           |    // There's more to this but this is all
+----+-------------+    // you need to answer this question
| ID | customer_id |
+----+-------------+

我需要找到在给定日期之后尚未订购的客户总数。

这就是我所做的:

SELECT Count(*)
FROM customers
LEFT JOIN orders ON customers.ID = orders.customer_id
WHERE customers.Created > #arbitrary date#
AND orders.ID Is Null;

我确信这是对的,但它似乎没有产生正确的结果。我的意思是我的老板正在查看结果并告诉我,根据经验,未订购的新客户注册数量远远超过此查询产生的数量。

我这样做是对的吗?如果我,我显然需要看看还有什么可能导致问题。感谢。

编辑1

以下评论表明orders.id不可为空。可能是这种情况,但是如果我检查orders.customer_id Is Null是否会得到相同的结果。

编辑2

我不想过于复杂化,但如果你知道我在Access数据库中这样做,那么它可能会很有用,所以我不能使用标准SQL允许的所有好东西。 (我编辑了标签)

5 个答案:

答案 0 :(得分:3)

你的老板必须告诉你他认为'好的价值观'。

也许他过去曾与其他人一起过滤报告以计算此客户。也许你必须检查订单表中某处的价格,如果价格= 0,则不要考虑真正的订单。

根据您提供的信息,您的查询绝对正确,也许我会添加一些内容:

SELECT Count(DISTINCT customers.ID)
FROM customers
    LEFT JOIN orders 
        ON customers.ID = orders.customer_id
WHERE customers.Created > #arbitrary date#
AND orders.ID Is Null;

为了更容易维护和理解(查询应该稍慢,但不是那么多)

答案 1 :(得分:1)

我想知道它们是否是一个微妙的错误 - 等待你的代码发生。

规范指出,“找到客户总数”。通过加入orders表,您实际上是指望加入。当然,对于没有订单的客户,您确实在计算客户。但是,对于订单的客户,您将计算他们的订单。

我更喜欢一个反映客户计数的查询结构,以便我(或者更确切地说是一个更随意的用户)可以将反连接切换到半连接并获得预期结果(使用您的构造,它们将获得误导性计数)例如

SELECT COUNT(*)
  FROM customers
 WHERE customers.Created > #specific date#
       AND NOT EXISTS (
                       SELECT *
                         FROM orders
                        WHERE orders.customer_id = customers.ID
                      );

至于接受的答案,我提供这个“为了更容易维护和理解”(查询可能会慢一点,但希望不是很多)。“

答案 2 :(得分:0)

也许某个地方您的代码允许为客户记录订单(但未完成)。 您可以计算仅订购0金额订单的客户。

SELECT COUNT(*)
FROM
  ( SELECT customers.id
    FROM customers
      INNER JOIN orders ON customers.ID = orders.customer_id
    WHERE customers.Created > #arbitrary date# 
    GROUP BY customers.id
    HAVING COUNT(IIF(orders.amount > 0, 1, NULL)) = 0  
  ) AS grp

Access没有CASE语句,但它有IIF()函数。

需要INNER JOIN而不是JOIN

答案 3 :(得分:-1)

不,这不对。

请改为尝试:

SELECT
SUM(CASE WHEN (SELECT COUNT(*) FROM orders WHERE customers.ID = orders.customer_id) = 0 
  THEN 1
  ELSE 0
END) 
FROM customers
WHERE customers.Created > #arbitrary date#

答案 4 :(得分:-1)

查看this website,它解释了sql连接之间的所有差异