Как заставить postgres возвращать 0, даже если нет строк, соответствующих запросу, используя coalesce, group by и join - PullRequest
0 голосов
/ 26 февраля 2019

Я безнадежно пытался получить следующий оператор SQL, чтобы вернуть результаты запроса, и по умолчанию 0, если нет строк, соответствующих запросу.

Это ожидаемый результат:

  vol  | year 
-------+------
   0   | 2018

Вместо этого я получаю:

 vol | year 
-----+------
(0 rows)

Вот выражение sql:

select coalesce(vol,0) as vol, year
from (select sum(vol) as vol, year
      from schema.fact_data
         join schema.period_data
            on schema.fact_data.period_tag = schema.period_data.tag 
         join schema.product_data
            on schema.fact_data.product_tag = 
schema.product_data.tag
         join schema.market_data
            on schema.fact_data.market_tag = schema.market_data.tag
      where "retailer"='MadeUpRetailer'
        and "product_tag"='FakeProductTag'
        and "year"='2018' group by year
     ) as DerivedTable;

Я знаю, что запрос работает, потому что он возвращает данные, когда есть данные.Просто не по умолчанию 0, как предполагалось ...

Любая помощь в выяснении, почему это так, будет высоко ценится!

Ответы [ 3 ]

0 голосов
/ 26 февраля 2019

Из кода, который вы разместили, не ясно, в какой таблице у вас есть столбец year.Вы можете использовать UNION для выборки только 1 строки, если в этой таблице для 2018 года нет строк, например:

select sum(vol) as vol, year
from schema.fact_data innrt join schema.period_data
on schema.fact_data.period_tag = schema.period_data.tag 
inner join schema.product_data
on schema.fact_data.product_tag = schema.product_data.tag
inner join schema.market_data
on schema.fact_data.market_tag = schema.market_data.tag
where 
  "retailer"='MadeUpRetailer' and 
  "product_tag"='FakeProductTag' and 
  "year"='2018'
group by "year"
union 
select 0 as vol, '2018' as year
where not exists (
  select 1 from tablename where "year" = '2018' 
)

Если есть строки для 2018 года, то ничего не будет выбрано2-й запрос

0 голосов
/ 26 февраля 2019

Удалите GROUP BY (и внешний запрос):

select 2018 as year, coalesce(sum(vol), 0) as vol
from schema.fact_data f join
     schema.period_data p
     on f.period_tag = p.tag join
     schema.product_data pr
     on f.product_tag = pr.tag join
     schema.market_data m
     on fd.market_tag = m.tag
where "retailer" = 'MadeUpRetailer' and
      "product_tag" = 'FakeProductTag' and
      "year" = '2018';

Запрос агрегации без GROUP BY всегда возвращает ровно одну строку, поэтому он должен делать то, что вы хотите.

РЕДАКТИРОВАТЬ:

Запрос будет выглядеть примерно так:

select v.yyyy as year, coalesce(sum(vol), 0) as vol
from (values (2018), (2019)) v(yyyy) left join
     schema.fact_data f
     on f.year = v.yyyy left join  -- this is just an example.  I have no idea where year is coming from
     schema.period_data p
     on f.period_tag = p.tag left join
     schema.product_data pr
     on f.product_tag = pr.tag left join
     schema.market_data m
     on fd.market_tag = m.tag
group by v.yyyy

Однако вы должны переместить условия where в соответствующие предложения on.Я понятия не имею, откуда берутся колонны.

0 голосов
/ 26 февраля 2019

Используя ваш подзапрос DerivedTable, вы можете написать:

SELECT coalesce(DerivedTable.vol, 0) AS vol,
       y.year
FROM (VALUES ('2018'::text)) AS y(year)
   LEFT JOIN (SELECT ...) AS DerivedTable
      ON DerivedTable.year = y.year;
...