Sql 缺少具有左联接和计数()的行所需的解释

Sql 缺少具有左联接和计数()的行所需的解释,sql,postgresql,aggregate-functions,Sql,Postgresql,Aggregate Functions,有人能帮我理解当我将WHERE子句添加到具有COUNT*左连接的查询时发生的以下行为吗 我有两张桌子: 现在,下面的查询告诉我每个客户下了多少订单: 这非常有效,但如果我在查询中添加WHERE子句,即使我正在进行左联接,对于没有下订单的客户,查询也不再输出零计数: select c.customer_id, count(o.order_id) from customers c left join orders o using (customer_id) where o.order_times

有人能帮我理解当我将WHERE子句添加到具有COUNT*左连接的查询时发生的以下行为吗

我有两张桌子:

现在,下面的查询告诉我每个客户下了多少订单:

这非常有效,但如果我在查询中添加WHERE子句,即使我正在进行左联接,对于没有下订单的客户,查询也不再输出零计数:

select c.customer_id, count(o.order_id)
from customers c
left join orders o using (customer_id)
where o.order_timestamp >= '2011-01-05'
group by 1

customer_id | count
-------------------
1 | 1
2 | 1
现在,如果我将WHERE条件作为左联接的一部分移动,如以下所示,我将返回未下订单的客户的零计数:

select c.customer_id, count(o.order_id)
from customers c
left join orders o on (c.customer_id = o.customer_id) and (o.order_timestamp >= '2011-01-05')
group by 1

我不明白为什么第二个查询不起作用,而第三个却起作用?有人能给我解释一下吗?也不确定这是否重要,但我正在使用postgres。谢谢

这是因为NULL不大于或等于任何值;如果将WHERE子句更改为WHERE o.order\U timestamp为null或o.order\U timestamp>='2011-01-05',则将获得与join子句限制相同的行为


不过请注意——我建议使用join子句方法,因为它更符合您要做的事情。此外,我上面提到的WHERE子句的更改仅在order_timestamp列不可为空的情况下才起作用-如果为空,则应使用不同的列进行空检查,例如,o.primarykey为空或o.order_timestamp>='2011-01-05'。

在处理右、左外部联接时,筛选条件的放置很重要。外部联接的ON子句中的条件在联接之前应用;WHERE子句中的条件在联接后应用-对使用联接的结果集应用

   SELECT c.customer_id, 
          COUNT(o.order_id)
     FROM CUSTOMERS c
LEFT JOIN ORDERS o ON o.customer_id - c.customer_id
                  AND o.order_timestamp >= '2011-01-05'
 GROUP BY c.customer_id
序数
序数是指使用指向SELECT子句中列的数字位置的数值,不建议使用序数。如果有人更改查询(比如添加列),可能会严重影响您的查询。

Chirs是对的,null不大于或等于任何值。所以,当您在where子句中包含您的条件时,它将应用于由left join生成的结果的最终viewtable, 在这个结果中,您的条件将删除时间戳为null的行

然而,当您在执行联接期间应用相同的条件时,该条件仅适用于订单表,而不适用于执行的左联接。因此,它不会删除时间戳为null的行


所以,在生成最终表之前应用的第三个查询条件和生成最终表之后应用的第二个查询条件中

谢谢-这确实有效!但是我还是很困惑。如果WHERE子句失败,该特定customer_id的零行不应该被合并,这意味着count*将为零?任何时候WHERE子句为特定行返回false时,该行将从结果集中排除;这发生在最终结果集上,而不是中间结果集上。当您将子句应用于联接时,它会按照您的建议执行。感谢您的解释!WHERE子句和您显示的JOIN子句之间的区别在于,当您在左侧JOIN子句上添加额外的约束时,您并没有改变这样一个事实,即JOIN左侧的表仍然返回,它只是没有与右侧表中的行匹配。当使用WHERE子句时,联接已经发生,现在您正在选择要返回的联接行中的哪一个。将约束添加到WHERE子句的一个主要含义是,查询将必须考虑所有O.OrrordTimeBayes值来确定是否为空。至少在我的例子中,这实际上破坏了我的300万行表中的索引。将约束添加到联接不会对性能产生负面影响。对我来说,我错过了GROUP BY。谢谢
select c.customer_id, count(o.order_id)
from customers c
left join orders o on (c.customer_id = o.customer_id) and (o.order_timestamp >= '2011-01-05')
group by 1
   SELECT c.customer_id, 
          COUNT(o.order_id)
     FROM CUSTOMERS c
LEFT JOIN ORDERS o ON o.customer_id - c.customer_id
                  AND o.order_timestamp >= '2011-01-05'
 GROUP BY c.customer_id