我有以下查询:
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
看起来这是不可能的,正如马修PK解释in his answer to a similar question。我错误地认为Postgres可以以某种方式从WHERE子句中提取缺失值。
有一些技能是可能的。 :)感谢Erwin Brandstetter!
答案 0 :(得分:6)
不可能吗?接受挑战。 :)
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;
这将为您提供完全您要求的内容。如果employee
和department
不是整数,则转换为匹配类型。
来自@ypercube的评论:count()需要位于items
的非空列上,因此我们为不存在的critera获取0
,而不是1
。< / p>
另外,将其他条件提升到LEFT JOIN
条件(本例中为i.available
),因此您不排除不存在的条件。
在评论中解决其他问题
这应该表现得很好。使用较长的标准列表,(LEFT) JOIN
可能是最快的方法。
如果您需要尽快,请务必创建multicolumn index之类的:
CREATE INDEX items_some_name_idx ON items (employee, department);
如果(employee, department)
应该是PRIMARY KEY
,或者您应该对这两列有UNIQUE
约束,那也可以解决这个问题。
答案 1 :(得分: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;
答案 2 :(得分:2)
基于Erwin的加入建议,这个really works:
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