SELECT COUNT(*) - 如果没有匹配的行,则返回0以及分组的字段

tok*_*rev 6 sql postgresql count aggregate-functions left-join

我有以下查询:

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;
Run Code Online (Sandbox Code Playgroud)

如果"employee-department"对没有项目,则查询不返回任何内容.我希望它返回零代替:

 employee | department | sum 
 ---------+------------+--------
 1        |          2 |      0
 3        |          4 |     12  
 5        |          6 |   1234   
Run Code Online (Sandbox Code Playgroud)

EDIT1

看起来这是不可能的,正如Matthew PK 在他对类似问题的回答中所解释的那样.我错误地假设Postgres可以以某种方式从WHERE子句中提取缺失值.

EDIT2

有一些技能是可能的.:)感谢Erwin Brandstetter!

Erw*_*ter 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;
Run Code Online (Sandbox Code Playgroud)

这将完全满足您的要求.如果employeedepartment不是整数,则转换为匹配类型.

来自@ypercube的评论:count()需要在非空列上items,所以我们得到的0是不存在的critera,而不是1.

此外,将其他条件纳入LEFT JOIN条件(i.available在本例中),因此您不排除不存在的条件.

性能

在评论中解决其他问题.
这应该表现得很好.使用较长的标准列表,(LEFT) JOIN可能是最快的方法.

如果您需要尽快,请务必创建一个多列索引,如:

CREATE INDEX items_some_name_idx ON items (employee, department);
Run Code Online (Sandbox Code Playgroud)

如果(employee, department)应该是PRIMARY KEY 或者你应该UNIQUE对两列有一个约束,那也可以做到这一点.

  • @Clodoaldo:这是*预期的*效果.问题中的查询具有其搜索的条件列表.问题是*不*寻找所有现有组合的完整列表.*使用`SELECT DISTINCT员工,部门FROM items`作为CTE`x`可以更容易实现*. (2认同)