从 LEFT JOIN 设置 NULL 列的默认值并使用 WHERE 过滤

Posted

技术标签:

【中文标题】从 LEFT JOIN 设置 NULL 列的默认值并使用 WHERE 过滤【英文标题】:Setting a default value on NULL columns from LEFT JOIN and filtering using WHERE 【发布时间】:2011-12-16 17:44:48 【问题描述】:

我有一个项目表,我有一个单独的表,其中包含每个项目的单独购买。并非所有物品都已购买。我正在选择购买计数并将其与 items 表中的语句类似:

SELECT items.name, purchases_count
FROM `items` 
    LEFT JOIN (SELECT sales.item_name, SUM(unit_sales) AS purchases_count 
        FROM sales GROUP BY item_name) sales ON sales.item_name = items.uid

这导致数据类似于:

+------+-----------------+
| name | purchases_count |
|------+-----------------+
| Shoe | 12              |
| Belt | NULL            |
+------+-----------------+

当我想在purchases_count 上过滤此结果时,我的问题出现了。如果我使用 WHERE purchases_count < 10 或类似名称,则根本没有销售记录的商品(即具有 NULL 值的商品)将被排除在搜索之外。

我尝试使用COALESCE(purchases_count,0) AS purchases_count,它确实将NULL 记录正确设置为0,但在使用WHERE 时它们仍然没有出现。我怀疑COALESCE 是在WHERE 之后发生的。

我希望能够使用WHERE 过滤此数字,并尽可能包含NULL 结果(作为零)。有什么建议吗?

【问题讨论】:

alias 的左连接表与表名相同,这是一种好习惯吗?? SQL 查询已被简化只是为了集中问题,实际的 SQL 与此不同。 【参考方案1】:

别名通常不适用于 WHERE 子句 - 尝试使用 COALESCE(purchases_count,0) AS purchases_count_2where purchases_count_2 < 10 来了解我的意思。

where COALESCE(purchases_count,0) < 10 应该可以工作。

【讨论】:

使用 purchase_count_2 不起作用,这与在正常的 purchase_count 上使用 COALESCE 的问题相同——它在 WHERE 子句中无法识别。 WHERE COALESCE(purchases_count,0) < 10 确实有效,但我宁愿找到一种不必在此处包装 COALESCE 的方法。不过,这可能是目前最好的选择,谢谢。 不确定这是否适用于 mysql,但您可以使用子查询:select * from (select ... coalesce(purchases_count,0) as purchases_count ...) where purchases_count < 10【参考方案2】:

不要在单独的查询中计算购买量,而是将主查询分组。要过滤计数,请将其放在 having caluse 中:

select i.name, coalesce(sum(s.unit_sales), 0) as purchases_count
from items i
left join sales s on s.item_name = i.uid
group by i.name
having purchases_count < 10

【讨论】:

【参考方案3】:

怎么样:

WHERE (purchases_count < 10) OR (purchases_count IS NULL)

当然,您仍然会留下空值,但您仍然可以尝试使用 COALESCE 选项将这些空值变为零以供以后使用。

【讨论】:

这个想法是我希望能够对这些数字应用任意过滤器,所以我不希望在我寻找 purchase_count > 6 时返回 NULL,例如,这将是使用这个的情况。【参考方案4】:

COALESCE 是正确的方法,但你不应该使用 WHERE,试试 :-

HAVING purchases_count<=10

【讨论】:

这是完全错误的。 HAVING 仅在使用 GROUP BY 时适用。 SQL 标准要求 HAVING 必须仅引用 GROUP BY 子句中的列或聚合函数中使用的列。但是,MySQL 支持对此行为的扩展,并允许 HAVING 引用 SELECT 列表中的列和外部子查询中的列。 啊。我懂了。感谢您澄清@ajreal。【参考方案5】:

所以,你可以像这样添加一个 where 子句:

 WHERE purchases_count < 10 OR purchases_count is NULL

【讨论】:

【参考方案6】:

你试试这个

SELECT items.name, IFNULL(purchases_count,0)
FROM `items` 
LEFT JOIN (
            SELECT item_name, SUM(unit_sales) AS purchases_count 
            FROM sales GROUP BY item_name
           ) s ON s.item_name = items.uid
GROUP BY items.name
HAVING purchases_count >10

【讨论】:

这是完全错误的。 HAVING 仅在使用 GROUP BY 时适用。 COALESCE 无论如何都不会在这里做任何事情,因为在子查询中没有 NULL 数据将 COALESCE 归零。 看到left join中有Group BY @James:无需分组即可使用。它用于将 where 样式的子句应用于聚合函数的结果,但不必进行聚合结果。 select x from y where x='1'select x from y having x='1' 是完全等价的,但是 where 子句在行级别进行过滤,并在结果级别进行过滤,紧接在结果发送到客户端之前。

以上是关于从 LEFT JOIN 设置 NULL 列的默认值并使用 WHERE 过滤的主要内容,如果未能解决你的问题,请参考以下文章

MYSQL Left Join 如何选择 NULL 值?

SQL:将所有没有默认值的列的默认值设置为 NULL

prisma:为啥我不能将“null”设置为可空列的默认值?

在 MariaDB 中显示 NULL 值(LEFT JOIN 给出错误值)

LINQ LEFT JOIN 不适用于 NULL 值

Big Query Tables 中列的默认值