sqlstored-proceduressnowflake-cloud-data-platform

How to loop through a SNOWFLAKE cursor and declare a string (cell value with delimiter) to a variable and pass inside where clause IN statement


I am trying to run a stored procedure which loops through a cursor gets the cell values into variables which I then pass it inside the where clause to filter. One of the cell contains a string with multiple values delimited by comma. I need to get these values into a variable and pass that variable into a where clause IN statement.

I have 3 tables

  1. Filter Criteria Table. I get these individual cell values into variables.
Country ITEM_LIST ORDER_QTY
US item1,item2 1
CA item5 1
  1. MAIN DATA TABLE. this is the table I filter against.
Country Order Number Item QTY
US 1.0 Item1 1
US 2.0 Item2 1
US 3.0 Item3 1
US 4.0 Item4 1
US 5.0 Item5 1
US 6.0 Item6 1
CA 7.0 Item1 1
CA 8.0 Item2 1
CA 9.0 Item3 1
CA 10.0 Item4 1
CA 11.0 Item5 1
CA 12.0 Item6 1

EXPECTED Output Result

3.OUTPUT TABLE.

Country Order Number Item Order Qty
US 1.0 Item1 1
US 2.0 Item2 1
CA 11.0 Item5 1

My code Below doesn't seem to work.

I am not sure how to do this using arrays which I believe it the right approach, any help will be appreciated. Thanks

 DECLARE 
    v_country STRING;
    v_item_list STRING;
    v_order_qty NUMBER;
    c1 CURSOR for (select * from FILTER_CRITERIA_TABLE);
    res RESULTSET;
    res_out RESULTSET;
BEGIN
    FOR rec IN c1 DO
            v_country := rec.COUNTRY ;
            v_item_list := rec.ITEM_LIST ;
            v_order_qty := rec.ORDER_QTY ;              
            res:=(
                    INSERT INTO OUTPUT_TABLE
                    
                    SELECT 
                        COUNTRY,
                        ORDER_NUMBER,
                        ITEM,
                        QTY,
                    FROM MAIN_DATA_TABLE
                    WHERE   
                        ITEM IN ( :v_item_list )
                        AND
                        COUNTRY = :v_country
                    );  
    END FOR;    
    res_out:=(select* from OUTPUT_TABLE);   
    RETURN TABLE(res_out); 
END;

Solution

  • You do not need a procedure for this. The following query should return the expected result:

    with country_items as 
    (
        select f.country, v.value::STRING item  from FILTER_CRITERIA_TABLE f,
        lateral flatten( split( item_list, ',') ) v
    )
    select m.* from MAIN_DATA_TABLE m
    join country_items c on m.country = c.country and upper(m.item) = upper(c.item);
    

    If you need to insert the values:

    insert into OUTPUT_TABLE
    with country_items as 
    (
        select f.country, v.value::STRING item  from FILTER_CRITERIA_TABLE f,
        lateral flatten( split( item_list, ',') ) v
    )
    select m.* from MAIN_DATA_TABLE m
    join country_items c on m.country = c.country and upper(m.item) = upper(c.item);
    

    If you want a SP:

    CREATE OR REPLACE PROCEDURE my_sp()
    RETURNS TABLE ()
    LANGUAGE SQL
    AS
    $$
    DECLARE
        res_out RESULTSET;
    BEGIN
        insert into OUTPUT_TABLE
        with country_items as 
        (
           select f.country, v.value::STRING item  from FILTER_CRITERIA_TABLE f,
           lateral flatten( split( item_list, ',') ) v
        )
        select m.* from MAIN_DATA_TABLE m
        join country_items c on m.country = c.country and upper(m.item) =    upper(c.item);
        res_out := (SELECT * FROM OUTPUT_TABLE); 
        RETURN TABLE(res_out); 
    END;
    $$