如果找不到记录,则使PostgreSQL返回值

时间:2017-10-31 00:07:48

标签: sql postgresql

我有一个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' );

我有什么遗失的吗?

3 个答案:

答案 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>