PostgreSQL从两个表中选择SELECT值

时间:2015-04-16 08:32:32

标签: sql postgresql select

我有问题要解决。

我有两个表,机构和文档,它们通过文件owner_id和机构ID加入:

机构

 id | name
----+-----
  1 | a
  2 | b
  3 | c
  4 | d

文件

   id | owner | value
  ----+-------+------
    1 |     1 | xxx
    2 |     1 | yyy
    3 |     1 | yyy
    4 |     3 | xxx
    5 |     3 | xxx
    6 |     4 | yyy

我需要算一下,每个名字有多少个值,这种结果:

 name | count(total) | count(xxx) | count(yyy)
------+--------------+------------+------------
 a    |            3 |          1 |          2
 b    |            0 |          0 |          0
 c    |            2 |          2 |          0
 d    |            1 |          0 |          1

我试过这个问题:

SELECT 
    a.name,
    (a.xxx + b.yyy) as total,
    a.xxx,
    b.yyy
FROM
    (SELECT count(documents.id) as xxx,
        institution.name
    FROM 
        documents, institution
    WHERE 
        documents.owner_id = institution.id and 
        documents.value = 'xxx'
    GROUP BY 
        institution.name) as a,
    (SELECT count(documents.id) as yyy,
        institution.name
    FROM 
        documents, 
        institution
    WHERE 
        documents.owner_id = institution.id and 
        documents.value = 'yyy'
    GROUP BY 
        institution.name) as b
WHERE 
a.name = b.name
ORDER BY 
a.name

但它只返回那些行,其中xxx和yyy不是epmty,这种:

 name | count(total) | count(xxx) | count(yyy)
------+--------------+------------+------------
 a    |            3 |          1 |          2

我错过了这些行:

 name | count(total) | count(xxx) | count(yyy)
------+--------------+------------+------------
 b    |            0 |          0 |          0
 c    |            2 |          2 |          0
 d    |            1 |          0 |          1

因为它包含空数据。 提前谢谢。

朱利

2 个答案:

答案 0 :(得分:1)

可以更轻松,尝试此解决方案

SELECT i.name,
       COUNT(*) total,
       COUNT(CASE d.value WHEN 'xxx' THEN 1 ELSE NULL END) x_cnt,
       COUNT(CASE d.value WHEN 'yyy' THEN 1 ELSE NULL END) y_cnt
FROM institution i
LEFT JOIN documents d ON d.owner = i.id
GROUP BY i.name

答案 1 :(得分:0)

除了agent5566:从版本9.4开始,您可以使用FILTER而不是CASE

SELECT  institution.name, 
    COUNT(documents.value) AS cnt_total, 
    COUNT(documents.value) FILTER(WHERE documents.value = 'xxx') AS cnt_xxx,
    COUNT(documents.value) FILTER(WHERE documents.value = 'yyy') AS cnt_yyy
FROM    institution
    LEFT JOIN documents ON documents.owner = institution.id
GROUP BY
    institution.name
ORDER BY
    institution.name;