Postgres 11.7中JOIN的误导计数为1

问题描述 投票:0回答:1

我在count(*)join周围遇到了微妙之处,希望能得到一些确认,我已经弄清楚了正在发生的事情。对于背景,我们通常将连续的时间轴数据转换为离散的bin,例如小时。而且,由于我们不希望没有内容的垃圾箱出现间隙,因此我们将使用generate_series来合成我们想要的值的存储桶。如果没有输入,例如10AM,很好,我们直到结果。但是,我注意到有时会得到1而不是0。这是我要确认的内容:

  • 如果计算“网格”系列,则计数为1,如果计算数据表,则计数为0。
  • 这仅与count有关,而与其他聚合无关。

下面的代码设置了一些示例数据来显示我在说什么:

DROP TABLE IF EXISTS analytics.measurement_table CASCADE;

CREATE TABLE IF NOT EXISTS analytics.measurement_table (
    hour smallint NOT NULL DEFAULT NULL,
    measurement smallint NOT NULL DEFAULT NULL
);


INSERT INTO measurement_table (hour, measurement)
     VALUES ( 0, 1),
            ( 1, 1),  ( 1, 1),
            (10, 2),  (10, 3), (10, 5); 

以下是查询的目标结果。我正在使用12个小时来使示例结果更短。

Hour Count sum
 0    1     1
 1    2     2
 2    0     0
 3    0     0
 4    0     0
 5    0     0
 6    0     0
 7    0     0
 8    0     0
 9    0     0
10    3    10
11    0     0
12    0     0

这可以正常工作:

WITH hour_series AS (
    select * from generate_series (0,12) AS hour
    ) 

    SELECT hour_series.hour,
           count(measurement_table.hour) AS frequency,
           COALESCE(sum(measurement_table.measurement), 0) AS total

      FROM hour_series
LEFT JOIN measurement_table ON (measurement_table.hour = hour_series.hour)

GROUP BY 1
ORDER BY 1

这将在比赛中返回误导性的1:

WITH hour_series AS (
    select * from generate_series (0,12) AS hour
    ) 

    SELECT hour_series.hour,
           count(*) AS frequency,
           COALESCE(sum(measurement_table.measurement), 0) AS total

      FROM hour_series
LEFT JOIN measurement_table ON (hour_series.hour = measurement_table.hour)

GROUP BY 1
ORDER BY 1
0   1   1
1   2   2
2   1   0
3   1   0
4   1   0
5   1   0
6   1   0
7   1   0
8   1   0
9   1   0
10  3   10
11  1   0
12  1   0

这两个示例之间的唯一区别是count术语:

count(*) -- A result of 1 on no match, and a correct count otherwise.
count(joined to table field) -- 0 on no match, correct count otherwise.

似乎就是这样,您必须明确指出要对数据表进行计数。否则,由于系列数据is匹配一次,您将获得1的计数。这是联接的细微差别,还是Postgres中count的细微差别?

这是否会影响其他汇总?似乎没有。

P.S。 generate_series几乎是有史以来最好的事情。

postgresql join count aggregate
1个回答
0
投票

您已正确解决问题:根据给定的参数,count()的行为有所不同。

count(*)计算属于该组的行数。只是不能为0,因为一个组中总是至少有一行(否则,就没有一个组)。

另一方面,当给定列名或表达式作为参数时,count()考虑任何非null值,而忽略null值。对于您的查询,这使您可以将left join ed表中不匹配的组与存在匹配项的组区分开。

© www.soinside.com 2019 - 2024. All rights reserved.