我有一个PostgreSQL 9.6表,如下所示:
range (string) count suburb
-------------- ------ ------
< 200,000 1 NEDLANDS
400,000 to 599,000 4 NEDLANDS
600,000 to 799,000 5 NEDLANDS
> 2 1 NEDLANDS
如果范围的计数为0,则表中没有记录,但我希望我的查询返回每个范围并报告0,其中不存在记录。因此,对于上表,所需的结果集将是:
range (string) count
-------------- ------
<200,000 1
200,000 to 400,000 0
400,000 to 599,000 4
600,000 to 799,000 5
800,000 to 1m 0
1m > 2m 0
> 2 1
我以为我可以union
查询查找记录但查询找不到记录的查询,但我的查询仍然找不到0计数记录:
select range, count
from sales
where suburb = 'NEDLANDS'
union all
select range, 0 as count from sales
where not exists (select range, count
from sales
where suburb = 'NEDLANDS' );
我有什么遗失的吗?
答案 0 :(得分:2)
最好的方法是拥有一个包含有效范围列表的表,例如valid_ranges
- 每个有效范围标题都有一行。
然后你可以去
SELECT vr.range, s.count
FROM valid_ranges vr
LEFT JOIN sales s ON vr.range = s.range
WHERE s.suburb = 'NEDLANDS' OR s.suburb IS NULL;
这最后一行有点奇怪。 “IS NULL”子句用于缺少的行,但为了使其正常工作,郊区不能是可为空的列。
如果郊区可以为空,您可以进行重组:
SELECT vr.range, n.count
FROM valid_ranges vr
LEFT JOIN (SELECT range, count FROM sales
WHERE suburb = 'NEDLANDS') n
ON vr.range = n.range;
如果无法创建有效范围表,则可以从sales表中获取所有范围。但这有风险,如果没有该范围的郊区,那么它根本不会显示在列表中:
SELECT vr.range, n.count
FROM (SELECT DISTINCT range FROM sales) vr
LEFT JOIN (SELECT range, count FROM sales
WHERE suburb = 'NEDLANDS') n
ON vr.range = n.range;
如果没有行,这些都将在计数中具有NULL。 如果你真的需要零,你可以使用COALESCE:
SELECT vr.range, COALESCE (n.count, 0)
FROM valid_ranges vr
LEFT JOIN (SELECT range, count FROM sales
WHERE suburb = 'REDLANDS') n
ON vr.range = n.range;
(编辑:更正了COALESCE()调用@craigcaulfield指出)
答案 1 :(得分:0)
您可以创建一个包含所有所需值的表,然后左键连接到您返回的值。
dummy_table:
dummy_field
<200,000
200,000 to 400,000
400,000 to 599,000
600,000 to 799,000
800,000 to 1m
1m > 2m
> 2
select *
from dummy_table
left join (select * from your subquery) on dummy_field = your_subquery_dummy_field
答案 2 :(得分:0)
形成所有范围值的小CTE(common table expression
)(或者可以更改为子查询),然后将现有查询加入
WITH MyRanges (range) AS (
select '<200,0001' as range union all
select '200,000 to 400,000' union all
select '400,000 to 599,000' union all
select '600,000 to 799,000' union all
select '800,000 to 1m' union all
select '1m > 2m' union all
select '> 2'
)
select
m.range
, coalesce(s.count,0)
from MyRanges m
left join (
select range, count
from sales
where suburb = 'NEDLANDS'
) s ON m.range = s.range
;
您可以扩展CTE的相同逻辑以保持范围的边界值,这可能会使查询的平衡变得更简单 - 但是并不清楚如何将计数准备到范围内。 / p>