计数为零的项目列表不存在

时间:2019-01-24 16:30:55

标签: sql postgresql count

如果我有一个带有以下内容的表t1

my_col
------
foo
foo
bar

我有一个包含foohello的列表

How can I get:

my_col | count
-------|-------
foo    | 2
hello  | 0

如果我愿意

SELECT my_col, COUNT(*) 
FROM t1
WHERE my_col in ('foo', 'hello')
GROUP BY my_col

我明白了

my_col | count
-------|------
foo    | 2

没有任何问候值。

我特别希望它引用项目列表,因为它将在列表是变量的程序中调用。

4 个答案:

答案 0 :(得分:3)

理想情况下,您应该维护一个单独的表,其中包含要显示在报告中的所有可能的列值。如果没有这种情况,我们可以在此处尝试使用CTE:

WITH cte AS (
    SELECT 'foo' AS my_col UNION ALL
    SELECT 'bar' UNION ALL
    SELECT 'hello'
)

SELECT
    a.my_col,
    COUNT(b.my_col) AS count
FROM cte a
LEFT JOIN t1 b
    ON a.my_col = b.my_col
WHERE
    a.my_col IN ('foo', 'hello')
GROUP BY
    a.my_col;

enter image description here

Demo

答案 1 :(得分:2)

您可以将列表变成一组行,并使用LEFT JOIN,例如:

SELECT x.val, COUNT(t.my_col) 
FROM 
    (SELECT 'foo' val UNION SELECT 'hello') x
    LEFT JOIN t ON t.my_col = x.val
GROUP BY x.val

答案 2 :(得分:2)

这是使用values的另一种方式:

select
  t2.my_col, count (t1.my_col)
from
  (values ('foo'), ('hello')) as t2 (my_col)
  left join t1 on t1.my_col = t2.my_col
group by
  t2.my_col

请注意,count (t1.my_col)为“ hello”返回0,因为不计算空值。 count (*)由contast会为“ hello”返回1,因为它正在计算行数。

答案 3 :(得分:1)

Postgres解决方案:

一种方法是将“列表”放入ARRAY中,然后使用unnest将ARRAY转换为列。然后在该列上与另一个表进行左连接并进行计数。

WITH t1 AS (
     SELECT 'foo' AS my_col UNION ALL
     SELECT 'foo' UNION ALL
     SELECT 'bar'
)

SELECT
    a.my_col,
    COUNT(b.my_col) AS count
FROM unnest(ARRAY['foo', 'hello']) a (my_col)
LEFT JOIN t1 b
    ON a.my_col = b.my_col
GROUP BY
    a.my_col;

我在其他答案上遇到的问题是(虽然他们帮助我找到了解决方案),但他们没有提供解决方案,其中感兴趣的项位于单个列表中(这不是实际的sql术语,所以问题就在我身上)。

但是,我的real use case是使用native queryjava执行hibernate的,不幸的是,上述操作不起作用,因为无法确定类型。相反,我将列表转换为单个字符串,并使用string_to_array代替了ARRAY函数。

因此,最适合我的用例的解决方案如下(但在这一点上,其他答案也将是正确的,因为我现在必须进行手动字符串操作,但我将其留在此处为了后代)

WITH t1 AS (
    SELECT 'foo' AS my_col UNION ALL
    SELECT 'foo' UNION ALL
    SELECT 'bar'
)

SELECT
    a.my_col,
    COUNT(b.my_col) AS count
FROM unnest(string_to_array('foo, hello', ',')) a (my_col)
LEFT JOIN t1 b
    ON a.my_col = b.my_col
GROUP BY
    a.my_col;