PL SQL脚本根据列值进行连接

时间:2016-12-19 06:11:42

标签: sql oracle plsql

我在编写PL SQL脚本时遇到困难。

我的要求是找到匹配的资产编号,将它们连接起来并插入基于逻辑的新表中。这里的逻辑是根据密钥查看是否存在匹配的资产编号。如果没有匹配的资产但密钥相同,则连接所有资产。

这是源表的样子

 
KEY     PR_AST_NUM     SEC_AST_NUM

1-24N   1-2428         1-2428
1-24N   1-2428         1-3032
1-24N   1-2428         1-3032
1-28N   1-3032         1-3436
1-28N   1-3842         1-4042
1-28N   1-5054         1-7284

这就是目标表的样子

 
KEY     CONCAT

1-24N   1-2428||1-2428
1-24N   1-2428||1-3032
1-28N   1-3032||1-3436||1-3842||1-4042||1-5054||1-7284

为了实现这一点,我首先编写了以下代码。但它并没有连接与密钥匹配的所有记录。你能帮我修改代码吗?

DECLARE

    K VARCHAR2(30);
    NK VARCHAR2(30);
    PST  VARCHAR2(30);
    NPST VARCHAR2(30);
    AST VARCHAR2(30);
    NAST VARCHAR2(30);

    M INTEGER(20) := 1;

    CURSOR PRDT IS 

    SELECT DISTINCT KEY,
           LEAD(KEY) OVER (ORDER BY KEY) AS NXTKEY,
           PR_AST_NUM,
           LEAD(PR_AST_NUM) OVER (ORDER BY KEY) AS NXTPRAST,
           SEC_AST_NUM,
           LEAD(SEC_AST_NUM) OVER (ORDER BY KEY) AS NXTSECAST
    FROM  DET_SRC
    ORDER BY KEY;

    BEGIN

    OPEN PRDT;

    LOOP

    FETCH PRDT INTO K, NK, PST, NPST, AST, NAST;

    EXIT WHEN PRDT%NOTFOUND;

    IF ((K = NK) AND (PST = NPST) AND (AST = NAST))
    THEN

    INSERT INTO DET_MOD
    VALUES (K, PST||'||'||AST);

    M := M + 1;

    ELSIF ((K = NK) AND (PST = NPST) AND (AST <> NAST))
    THEN

    M := 1;

    INSERT INTO DET_MOD
    VALUES (K, PST||'||'||AST);

    ELSIF ((K = NK) AND (PST <> NPST) AND (AST <> NAST))
    THEN

    INSERT INTO DET_MOD
    VALUES (K, PST||'||'||AST);

    M := 1;

    END IF;

    END LOOP;

    COMMIT;

    CLOSE PRDT;

    END;

这是代码的输出。如您所见,它不是连接到下一行,而是创建一个新行并错过最后一个条件。

 
    KEY     CONCAT
    1-24N   1-2428||1-2428
    1-24N   1-2428||1-3032
    1-28N   1-3032||1-3436
    1-28N   1-3842||1-4042

谢谢!

3 个答案:

答案 0 :(得分:2)

查看此直播Demo

在光标或函数或任何其他代码中使用以下查询来获取结果。

代码:

            select KEY, LISTAGG(AST_NUM, '||') WITHIN GROUP (ORDER BY KEY) 
            as CONCAT_ASSET_NUM
            from 
            (select   distinct KEY ,  Concat(PR_AST_NUM , Concat('||',SEC_AST_NUM))  
            as AST_NUM
            from DET
            where PR_AST_NUM=SEC_AST_NUM
            Order by KEY 

            )b 
            group by KEY


            union all

            select KEY, LISTAGG(AST_NUM, '||') WITHIN GROUP (ORDER BY KEY) 
            as CONCAT_ASSET_NUM
            from 
            (select   distinct KEY ,  Concat(PR_AST_NUM , Concat('||',SEC_AST_NUM))  
            as AST_NUM
            from DET
            where PR_AST_NUM!=SEC_AST_NUM
            Order by KEY 

            )a 
            group by KEY
  

输出:

enter image description here

答案 1 :(得分:1)

请你试试这个:

SELECT val1, LISTAGG(val2, ', ') WITHIN GROUP (ORDER BY val2) AS value2
from (
    select KEY as val1, PR_AST_NUM as val2 from myTable 
    union all     
    select key, SEC_AST_NUM from myTable) t group by val1

答案 2 :(得分:1)

这会为您提供所需的结果

select      key
           ,listagg (PR_AST_NUM || '||' || SEC_AST_NUM,'||') 
                within group (order by PR_AST_NUM) as concat

from       (select      distinct
                        key,PR_AST_NUM,SEC_AST_NUM

            from        mytable                 
            ) 

group by    key
           ,case when PR_AST_NUM = SEC_AST_NUM then PR_AST_NUM end
+-------+------------------------------------------------+
| KEY   | CONCAT                                         |
+-------+------------------------------------------------+
| 1-24N | 1-2428||1-3032                                 |
+-------+------------------------------------------------+
| 1-24N | 1-2428||1-2428                                 |
+-------+------------------------------------------------+
| 1-28N | 1-3032||1-3436||1-3842||1-4042||1-5054||1-7284 |
+-------+------------------------------------------------+