从 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_2
和 where 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 过滤的主要内容,如果未能解决你的问题,请参考以下文章
prisma:为啥我不能将“null”设置为可空列的默认值?