Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Returning tabular data from Snowflake SQL procedure

I’m trying to write a stored procedure that will return the results of a complex query:

CREATE OR REPLACE PROCEDURE sp_partition_ohlc(symbol VARCHAR(10), 
                                              from_time NUMERIC(20, 0), 
                                              til_time NUMERIC(20, 0),  
                                              step_time NUMERIC(20, 0))
    RETURNS TABLE()
    LANGUAGE SQL
    AS
    $$
    BEGIN
        SELECT 
            :step_time * bucket AS t,
            SUM(T.volume) AS v,
            MAX(T.open) AS o,
            MAX(T.close) AS c,
            MAX(T.highlow) AS h,
            MIN(T.highlow) AS l,
            v * (h + l + c) / 3 AS wv,
            COUNT(*) AS n
        FROM (
            SELECT
                FLOOR(T.sip_timestamp / :step_time) AS bucket,
                cta_calc(T.size, T.conditions, 'VOLUME') AS volume,
                cta_calc(T.price, T.conditions, 'HIGHLOW') AS highlow,
                IFF(ROW_NUMBER() OVER (PARTITION BY bucket ORDER BY T.sip_timestamp) = 1, T.price, NULL) AS open,
                LAST_VALUE(cta_calc(T.price, T.conditions, 'LAST')) 
                    IGNORE NULLS OVER (PARTITION BY bucket ORDER BY T.sip_timestamp) AS close
            FROM trades AS T
            WHERE 
                T.symbol = :symbol AND 
                T.sip_timestamp >= :from_time AND
                T.sip_timestamp < :til_time) AS T
        GROUP BY bucket
        ORDER BY bucket;
    END
    $$

This compiles properly but, if I try to run it:

CALL sp_partition_ohlc('NTAP', 1640995200000000000, 1672531200000000000, 3600000000000)

I get the following error:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

092222 (P0000): SQL compilation error: stored procedure is missing a return statement

From this, I understand that I should have a RETURN in front of my outer SELECT statement. However, when I modify the procedure thus, it fails to compile with this error:

Syntax error: unexpected ‘SELECT’. (line 7)
syntax error line 4 at position 23 unexpected ‘*’. (line 7)

I’m not sure what this error is telling me as, when I run the query by itself, it returns results. I assume I’m doing something wrong in setting up the procedure but I’m not sure what it is from the associated documentation, here. Any help would be appreciated.

>Solution :

It is not a matter of just putting a return in there:

you more want to follow a pattern like:

create or replace procedure get_top_sales()
returns table (sales_date date, quantity number)
language sql
as
declare
  res resultset default (select sales_date, quantity from sales order by quantity desc limit 10);
begin
  return table(res);
end;

here the res is a declared as the result set, which is the SQL to run, so you can access those, and then it is returned as a table via table(res) and the type of the res matches the return type of the function returns table (sales_date date, quantity number), so for your function you would need to alter this also.

so something like (I have not run):

CREATE OR REPLACE PROCEDURE sp_partition_ohlc(symbol VARCHAR(10), 
                                              from_time NUMERIC(20, 0), 
                                              til_time NUMERIC(20, 0),  
                                              step_time NUMERIC(20, 0))
    RETURNS TABLE(t int, v float, o float, c float, h float, l float, wv float, n int) /* guessed types */
    LANGUAGE SQL
    AS
    $$
    DECLARE
        res resultset;
    BEGIN
    
        let res := (
            SELECT 
                :step_time * bucket AS t,
                SUM(T.volume) AS v,
                MAX(T.open) AS o,
                MAX(T.close) AS c,
                MAX(T.highlow) AS h,
                MIN(T.highlow) AS l,
                v * (h + l + c) / 3 AS wv,
                COUNT(*) AS n
            FROM (
                SELECT
                    FLOOR(T.sip_timestamp / :step_time) AS bucket,
                    cta_calc(T.size, T.conditions, 'VOLUME') AS volume,
                    cta_calc(T.price, T.conditions, 'HIGHLOW') AS highlow,
                    IFF(ROW_NUMBER() OVER (PARTITION BY bucket ORDER BY T.sip_timestamp) = 1, T.price, NULL) AS open,
                    LAST_VALUE(cta_calc(T.price, T.conditions, 'LAST')) 
                        IGNORE NULLS OVER (PARTITION BY bucket ORDER BY T.sip_timestamp) AS close
                FROM trades AS T
                WHERE 
                    T.symbol = :symbol AND 
                    T.sip_timestamp >= :from_time AND
                    T.sip_timestamp < :til_time) AS T
            GROUP BY bucket
            ORDER BY bucket
        );
        
        return table(res);
    END
    $$
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading