Sql 选择计数(*)-如果没有匹配的行,则返回0和分组字段
我有以下疑问:Sql 选择计数(*)-如果没有匹配的行,则返回0和分组字段,sql,postgresql,count,left-join,aggregate-functions,Sql,Postgresql,Count,Left Join,Aggregate Functions,我有以下疑问: SELECT employee,department,count(*) AS sum FROM items WHERE ((employee = 1 AND department = 2) OR (employee = 3 AND department = 4) OR (employee = 5 AND department = 6) OR ([more conditions with the same structure]))
SELECT employee,department,count(*) AS sum FROM items
WHERE ((employee = 1 AND department = 2) OR
(employee = 3 AND department = 4) OR
(employee = 5 AND department = 6) OR
([more conditions with the same structure]))
AND available = true
GROUP BY employee, department;
如果一对“employee department”没有项目,则查询不返回任何内容。我希望它返回零:
employee | department | sum
---------+------------+--------
1 | 2 | 0
3 | 4 | 12
5 | 6 | 1234
编辑1
正如Matthew PK所解释的,看起来这是不可能的。我错误地认为Postgres可以从WHERE子句中提取缺失的值
编辑2
通过一些技巧,这是可能的。:)感谢欧文·布兰德施泰特 不可能?接受挑战。:)
select employee, department,
count(
(employee = 1 and department = 2) or
(employee = 3 and department = 4) or
(employee = 5 and department = 6) or
null
) as sum
from items
where available = true
group by employee, department;
这将完全满足您的要求。如果employee
和department
不是整数,则转换为匹配类型
@ypercube:count()的每条注释需要位于项的非空列上,因此我们得到的0
是不存在的标准,而不是1
另外,将其他条件拉入左连接
条件(i.available
,在本例中),这样就不会排除不存在的条件
演出
在评论中提出其他问题。
这应该表现得很好。对于较长的标准列表,(左)JOIN
可能是最快的方法
如果需要,请尽快创建一个类似的:
如果(员工、部门)
应该是主键
,或者您应该在这两列上有一个唯一的
约束,这也会起到作用。基于Erwin的加入建议,这个:
你只想要WHERE子句中的雇员和部门组吗?@FarukSahin,实际上不,可能还有其他子句,但我只想按“雇员”和“部门”分组。更新问题accordingly@FarukSahin,误读了你的评论。在输出中,我只需要分组字段和总和。因此,要限制某些(员工、部门)组的输出,不需要所有(员工、部门)组?我没有看到标记为postgresql。检查这个链接,在那里同样的问题得到了回答:Nicebool或null
,从未想过这个优雅的解决方案。但是使用NULLIF((条件),'false')
可能更容易阅读。或者SUM(当…然后是1或0结束时的情况)
。如果表中不存在给定的“员工部门”对,则该操作无效。查看我对question@Igor一旦你习惯了它(它会很快),你就会欣赏它带来的清洁。这真是太棒了:)接下来的问题——这个查询的性能如何?(桌子会很大)。我可以选择在应用程序中实现所要求的功能level@tokarev:我在回答中添加了一点。是的,但只有在CTE中不存在新的配对时,才会将其添加到表中。@Clodoaldo:这是预期效果。问题中的查询具有其搜索的条件列表。问题不是寻找所有现有组合的完整列表。使用从项目中选择不同的员工、部门
作为CTEx
,这将更容易实现。
WITH x(employee, department) AS (
VALUES
(1::int, 2::int)
,(3, 4)
,(5, 6)
-- ... more combinations
)
SELECT x.employee, x.department, count(i.employee) AS ct
FROM x
LEFT JOIN items i ON i.employee = x.employee
AND i.department = x.department
AND i.available
GROUP BY x.employee, x.department;
CREATE INDEX items_some_name_idx ON items (employee, department);
with x(employee, department) as (
values (1, 2)
)
select
coalesce(i.employee, x.employee) as employee,
coalesce(i.department, x.department) as department,
count(available or null) as ct
from
x
full join
items i on
i.employee = x.employee
and
i.department = x.department
group by 1, 2
order by employee, department