右联接后如何计算左表中的缺失行?

时间:2020-01-26 13:08:18

标签: sql postgresql join count left-join

有两个表:

education_data(每个衡量指标按年份列出的国家列表)。

create table education_data 
(country_id int,
indicator_id int,
year date,
value float
);

indicators(所有指标列表):

create table indicators
(id int PRIMARY KEY,
name varchar(200),
code varchar(25)
);

我想找到数量最多的国家完全缺乏信息的指标 即最大值(按国家/地区缺失指标的数量)

我已经解决了excel中的问题(通过按国家/地区在数据透视表中计算空白)

pivot table with count for missing indicators by country

我还没有想到我们的SQL查询是否可以返回相同的结果。

我能够返回某个国家/地区缺少的指标数量,请在下面的查询中查询,但不是所有国家/地区都可以。

SELECT COUNT(*)
FROM education_data AS edu
RIGHT JOIN indicators AS ind ON
edu.indicator_id = ind.id and country_id = 10 
WHERE value IS NULL 
GROUP BY country_id

到目前为止,我已经尝试过交叉连接,但没有成功。

2 个答案:

答案 0 :(得分:0)

我想找到最缺乏国家信息的指标,即完全缺乏信息的国家(即最大(按国家/地区缺少指标的数量)

这是一个逻辑矛盾。 ...

国家缺少指标的数量

..无法固定在任何特定指标上,因为这些国家/地区没有 指标。

带有“缺失指标”(即indicator_id IS NULL)的每个国家/地区的计数

SELECT country_id, count(*) AS ct_indicator_null
FROM   education_data
WHERE  indicator_id IS NULL
GROUP  BY country_id
ORDER  BY count(*) DESC;

或更笼统地说,没有有效的指示符,该指示符还包括其中indicator_id与表indicators不匹配的行:

SELECT country_id, count(*) AS ct_no_valid_indicator
FROM   education_data e 
WHERE  NOT EXISTS (
   SELECT FROM indicators i
   WHERE  i.id = e.indicator_id
   )
GROUP  BY country_id
ORDER  BY count(*) DESC;

NOT EXISTS是此处适用的四种基本技术之一(LEFT / RIGHT JOIN,就像您尝试过使用另一种一样)。参见:

您提到了country表。 education_data中没有任何指标条目的国家/地区不包括在上面的结果中。也要找到这些内容:

SELECT *
FROM   country c
WHERE  NOT EXISTS (
   SELECT
   FROM   education_data e
   JOIN   indicators     i ON i.id = e.indicator_id  -- INNER JOIN this time!
   WHERE  e.country_id = c.id
   );

报告没有有效指标(无或无效)的国家/地区。


如果每个国家/地区都应该有一个有效的指标,请在清理现有数据后考虑:

..使您更接近有效的多对多实施。参见:

答案 1 :(得分:0)

您也必须加入contries,否则您将无法确定contry是否在education_data中根本没有条目:

create table countries(id serial primary key, name varchar);
create table indicators
(id int PRIMARY KEY,
name varchar(200),
code varchar(25)
);
create table education_data 
(country_id int references countries,
indicator_id int references indicators,
year date,
value float
);

insert into countries values (1,'USA');
insert into countries values (2,'Norway');
insert into countries values (3,'France');
insert into indicators values (1,'foo','xxx');
insert into indicators values (2,'bar', 'yyy');
insert into education_data  values(1,1,'01-01-2020',1.1);

SELECT count (c.id), i.id, i.name
FROM countries c JOIN indicators i ON (true) LEFT JOIN education_data e ON(c.id = e.country_id AND i.id = e.indicator_id) 
WHERE indicator_id IS NULL
GROUP BY i.id;


count | id | name 
-------+----+------
     3 |  2 | bar
     2 |  1 | foo
(2 rows)