Skip to content
Advertisement

Variable in dateadd function snowflake

I have a query like this:

With cte as(
    Select min(date1) as min_date,
           max(date1) as max_date,
           id,
           city,
           time_id
   From some_table
   Group by id, city, time_id
),

range as
(select dateadd('month', row_number()over(order by null), (select min_date from cte)) as date_expand
From table(generator (row_count => 12*36))))

Select * from range;

It gives this error: Single row subquery returns more than one row.

Is there a way to pass a variable in the 3rd argument of dateadd function? Because my cte will return many min_date based on the group by clause. TIA

Advertisement

Answer

Yes, sub-select in SELECT need to only return one row, you have many rows in your CTE.

You query makes more sense to me if you did something like this:

With some_table as (
    SELECT * FROM VALUES
        (1, 'new york', 10, '2020-01-01'::date),
        (1, 'new york', 10, '2020-02-01'::date),
        (2, 'christchurch', 20, '2021-01-01'::date)
    v(id, city, time_id, date1)
), cte as (
    Select 
       min(date1) as min_date,
       max(date1) as max_date,
       id,
       city,
       time_id
   FROM some_table
   GROUP BY 3,4,5
), range as (
    SELECT 
        id, city, time_id,
        dateadd('month', row_number()over(partition by id, city, time_id ORDER BY null), min_date) as date_expand
    FROM table(generator(rowcount =>12*36))
    CROSS JOIN cte
)
Select * from range;

but if your CTE was changing to be like this:

With cte as (
    Select 
       min(date1) as min_date,
       max(date1) as max_date
   FROM some_table
), range as (
    SELECT 
        dateadd('month', row_number()over(ORDER BY null), (select min_date from cte)) as date_expand
    FROM table(generator(rowcount =>2*4))
)
Select * from range;

this would work, as there is only one min_date value returned.

OR you could find the smallest of the min_dates like:

WITH cte as (
    Select 
       min(date1) as min_date,
       max(date1) as max_date,
       id,
       city,
       time_id
   FROM some_table
   GROUP BY 3,4,5
), range as (
    SELECT 
        dateadd('month', row_number()over(ORDER BY null), (select min(min_date) from cte)) as date_expand
    FROM table(generator(rowcount =>2*3))

)
Select * from range;
User contributions licensed under: CC BY-SA
4 People found this is helpful
Advertisement