Search code examples
sqlpostgresqlsql-functiongenerate-serieschartio

Set-returning functions are not allowed in CASE in postgreSQL


I am trying to run this query was able to till some time ago. I don't know what went wrong and I started getting this error now?

Your database returned: ERROR: set-returning functions are not allowed in CASE Hint: You might be able to move the set-returning function into a LATERAL FROM item.

My query:

SELECT distinct
(CASE
WHEN {PERIOD} = 'Previous Quarter' AND pto.pto_start_date < (date_trunc('quarter', now() - INTERVAL '1 month') + INTERVAL '1 month')::date AND pto.pto_end_date >= (date_trunc('quarter', now() - INTERVAL '1 month') + INTERVAL '1 month')::date
THEN generate_series(pto.pto_start_date, pto.pto_end_date, '2 day'::interval)
WHEN {PERIOD} = 'Current Quarter' AND pto.pto_start_date < (date_trunc('quarter', now() - INTERVAL '1 month') + INTERVAL '1 month')::date AND pto.pto_end_date >= (date_trunc('quarter', now() - INTERVAL '1 month') + INTERVAL '1 month')::date
THEN generate_series(pto.pto_start_date, pto.pto_end_date, '1 day'::interval)
ELSE
generate_series(pto.pto_start_date, pto.pto_end_date, '1 day'::interval)
END) AS dt
FROM cust_pto pto

Start dates and end Dates:

enter image description here

What has gone wrong?


Solution

  • Why you're getting the error now: you upgraded to postgres 10. Set returning functions are no longer allowed.

    What to do: there is more than one way to accomplish what you're trying to do. For the sake of keeping it as close as possible to your original query, all you have to do is put your CASE statement inside generate_series:

    SELECT distinct generate_series(
            pto.pto_start_date,
            pto.pto_end_date,
            CASE
            WHEN {PERIOD} = 'Previous Quarter' AND pto.pto_start_date < (date_trunc('quarter', now() - INTERVAL '1 month') + INTERVAL '1 month')::date AND pto.pto_end_date >= (date_trunc('quarter', now() - INTERVAL '1 month') + INTERVAL '1 month')::date THEN
                '2 day'::interval
            ELSE
                '1 day'::interval
            END
    ) AS dt
    FROM cust_pto pto