Preserve all elements of an array while (left) joining to a table

社会主义新天地 提交于 2019-12-13 04:19:38

问题


I'm trying to pull from my expenses table all 12 months expenses, group by month. If there are no results in one month, I still wish to receive this month worth 0 (zero) value result.

My database is PostgreSQL 9.1.

I wrote this query, but I don't succeed to execute it or understand how to correct it.

SELECT fta.liability_id, fta.amount
     , date_part('month', fta.act_date) AS act_month
FROM  (
   select i
   from generate_series(1,array_upper(ARRAY[1,2,3,4,5,6,7,8,9,10,11,12],1)) i) as ym
LEFT OUTER JOIN financial_t_account fta on ym.i = fta.act_month;

回答1:


The fault is that you try to refer to an output column's name (act_month) in the JOIN condition, where it is not visible - it is not calculated yet! Try:

SELECT fta.liability_id
      ,fta.amount
      ,date_part('month', fta.act_date) AS act_month
FROM  (
   SELECT i
   FROM   generate_series(1,array_upper(ARRAY[1,2,3,4,5,6,7,8,9,10,11,12],1)) i
   ) ym
LEFT JOIN financial_t_account fta
          ON ym.i = date_part('month', fta.act_date)::int;

You can largely simplify to:

SELECT fta.liability_id
      ,fta.amount
      ,date_part('month', fta.act_date) AS act_month
FROM   generate_series(1,12) ym(i)
LEFT   JOIN financial_t_account fta
            ON ym.i = date_part('month', fta.act_date)::int;

Or, if you want arbitrary months from an array, use unnest() instead of generate_series():

... 
FROM   unnest(ARRAY[1,2,4,57,8,11,12]) ym(i)
...

Use a CTE (or a subquery) to avoid repeating the expression (and evaluating it twice):

WITH x AS (
   SELECT *, date_part('month', act_date)::int As act_month
   FROM financial_t_account
)
SELECT x.liability_id
      ,x.amount
      ,x.act_month
FROM   generate_series(1,12) ym(i)
LEFT   JOIN x ON ym.i = x.act_month;


来源:https://stackoverflow.com/questions/11242182/preserve-all-elements-of-an-array-while-left-joining-to-a-table

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!