7

私は次のクエリを持っています:

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句から欠落している値を何らかの方法で抽出できると誤って想定していました。

EDIT2

いくつかのスキルで可能です。:) Erwin Brandstetterに感謝します!

4

3 に答える 3

7

ありえない?勝負を受けて立つ。:)

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;

これはあなたが求めているものを正確に与えるでしょう。employeedepartmentが整数でない場合は、一致する型にキャストします。

@ypercubeからのコメントによると、count()はのnull以外の列にある必要があるため、存在しない基準ではなくitems、を取得01ます。

また、LEFT JOIN条件に追加の基準をプルアップして(i.availableこの場合)、存在しない基準を除外しないようにします。

パフォーマンス

コメントで追加の質問に対処します。
これは非常にうまく機能するはずです。基準のリストが長い場合(LEFT) JOINは、おそらく最速の方法です。

できるだけ速く必要な場合は、次のような複数列のインデックスを作成してください。

CREATE INDEX items_some_name_idx ON items (employee, department);

(employee, department)である必要がある場合、PRIMARY KEY またはUNIQUE2つの列に制約がある場合は、それでもうまくいきます。

于 2012-12-10T16:21:03.287 に答える
2

アーウィンの参加提案に基づいて、これは実際に機能します:

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
于 2012-12-10T17:17:55.380 に答える
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;
于 2012-12-10T14:58:39.953 に答える