最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

sql - How to loop through a SNOWFLAKE cursor and declare a string (cell value with delimiter) to a variable and pass inside wher

programmeradmin5浏览0评论

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

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;
Share Improve this question edited Mar 11 at 18:17 Aaqil Rahman asked Mar 11 at 6:16 Aaqil RahmanAaqil Rahman 155 bronze badges 3
  • "I have 3 tables" - but you only show 2? – Dale K Commented Mar 11 at 7:24
  • The third Table is the output table where I will be inserting the result set into. Thanks – Aaqil Rahman Commented Mar 11 at 18:13
  • In that you have 2 tables and you wish to create a third. – Dale K Commented Mar 11 at 18:25
Add a comment  | 

2 Answers 2

Reset to default 1

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;
$$

Since you mentioned you wanted to use array variable, I have just made slight modification to your code.

  • C1 cursor selects only items and country as we need those to filter the main table.
SELECT country,TRIM(VALUE::STRING) AS item
FROM filter_criteria_table,
LATERAL FLATTEN(input => SPLIT(ITEM_LIST, ','))
  • In each iteration of the loop, INSERT runs and a row is inserted.

Approach using variables


CREATE OR REPLACE PROCEDURE filter_data()
RETURNS TABLE ()
LANGUAGE SQL
AS
$$
DECLARE 
    v_country STRING;
    v_item_list STRING;
    c1 CURSOR for (SELECT
            country,TRIM(VALUE::STRING) AS item
        FROM filter_criteria_table,
        LATERAL FLATTEN(input => SPLIT(ITEM_LIST, ',')));

    res_out RESULTSET;
BEGIN
    FOR rec IN c1 DO
        v_country := rec.COUNTRY;
        v_item_list := rec.item;
        
                   
            INSERT INTO OUTPUT_TABLE
            SELECT 
                COUNTRY,
                ORDER_NUMBER,
                ITEM,
                QTY
            FROM MAIN_DATA_TABLE
            WHERE   
                 upper(ITEM) = upper(:v_item_list)
                AND COUNTRY = :v_country
       ;
    END FOR;

    res_out := (SELECT * FROM OUTPUT_TABLE); 
    RETURN TABLE(res_out); 
END;
$$;

Calling the procedure

CALL filter_data();

Outputs

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论