返回列表中串联列表的单个输出行的最佳 pl/sql 策略

问题描述 投票:0回答:1

我有以下数据样本。

Levl        Clan            Skills          WpnCode
100         Daredevil       Beginner        Stick
100         Daredevil       Archery         Archblst
100         Daredevil       Archery         Archaccy
100         Daredevil       Powershot       Cannon
100         Daredevil       Powershot       Rifle
125         Bluesy          Beginner        
125         Bluesy          Archery         Greenarch
125         Bluesy          Archery         Bluearch
125         Bluesy          Powershot       Torch
125         Bluesy          Powershot       Knife
150         Stargaze        Beginner        None
150         Stargaze        Powershot       Magnum
150         Stargaze        Powershot       Pistol

期望的输出:

varProf = Daredevil-Archblst,ArchAccy[Cannon,Rifle]
varProf2 = Bluesy-Greenarch,Bluearch[Torch,Knife],Stargaze[Magnum,Pistol]

首次尝试仅返回 varProf:

 DECLARE
    varProf VARCHAR2(500) := '';
 BEGIN
    SELECT
        LISTAGG(
            CASE 
                WHEN PSWpn = 'Beginner' THEN Clan
                ELSE Clan || '[' || WpnList || ']'
            END,
            '-'
        ) WITHIN GROUP (ORDER BY Levl) INTO varProf
    FROM (
        SELECT = Clan, PSWpn, Levl,
            LISTAGG(WpnCode, ',') WITHIN GROUP (ORDER BY WpnCode) AS WpnList
        FROM (
            SELECT
                Club AS Clan,
                CASE WHEN Skills = 'Powershot' THEN 'Powershot' ELSE 'Beginner' END AS PSWpn,
                Level AS Levl,
                Weapons AS WpnCode
            FROM
                -- my joins are here
            WHERE
                -- my conditions and prompts are here
        )
        GROUP BY Clan, PSWpn, Levl
    );

    DBMS_OUTPUT.PUT_LINE('varProf = ' ||varProf);
 END;

这是不对的,因为它附加了(-)氏族而不是射箭技能。

所以我尝试使用另一种策略,仅循环记录:

 DECLARE
  varProf VARCHAR2(500) := '';
  varProf2 VARCHAR2(500) := '';
 BEGIN
  FOR rec IN (
    SELECT Club AS Clan, Weapons AS WpnCode, Level AS Levl, Skills 
    FROM
        -- my tables
    WHERE
        -- my conditions 
   ) LOOP
    IF rec.Levl = 1 THEN
        IF varProf IS NULL OR varProf = '' THEN
           varProf := rec.Clan || '-' || rec.WpnCode;
        ELSE
            varProf := varProf || ',' || rec.Clan || '-' || rec.WpnCode;
        END IF;
    ELSE
        IF varProf2 IS NULL OR varProf2 = '' THEN
           varProf2 := rec.Clan || '-' || rec.WpnCode;
        ELSE
            varProf2 := varProf2 || ', ' || rec.Clan || '-' || rec.WpnCode;
        END IF;
    END IF;
END LOOP;

DBMS_OUTPUT.PUT_LINE('varProf = ' || varProf);
DBMS_OUTPUT.PUT_LINE('varProf2 = ' || varProf2);
END;

虽然它确实附加了技能,但我没有包含 WpnCode 的 listagg...是否有更好的策略来获得我想要的所需输出?

基本上,示例数据针对一个用户及其个人资料(我有条件在 where 子句中提示输入用户名)。但无论如何,我想返回他们的初学者氏族名称(由等级 100 和技能 = 初学者标识)。后面跟着一个“-”来附加他们的射箭武器(如果有多个,则用“,”分隔),由技能 = 射箭来标识。最后附加一个封闭的 [ ],里面是 Powershot 武器/WpnCode 的列表,如果有多个 WpnCode,则用逗号分隔,并且通过 Skills = Powershot 来标识。

然后,我还想显示非初学者部落名称,由等级 <> 100 标识。使用与上面相同的逻辑,但主要区别在于它们可以有多个非初学者部落,这是我想要的它们也清楚地列出(没有欺骗),用逗号分隔。

这里再次是所需的输出:

varProf = Daredevil-Archblst,ArchAccy[Cannon,Rifle]
varProf2 = Bluesy-Greenarch,Bluearch[Torch,Knife],Stargaze[Magnum,Pistol]
oracle stored-procedures plsql concatenation listagg
1个回答
0
投票

一定是PL/SQL吗?如果是这样,请将以下查询拆分为两个单独的 SELECT。

SQL> select a.clan ||'-'||
  2         listagg(distinct b.wpncode, ',') ||'[' ||
  3         listagg(distinct c.wpncode, ',') ||']' as result
  4  from test a left join test b on a.clan = b.clan and b.skills = 'Archery'
  5              left join test c on c.clan = a.clan and c.skills = 'Powershot'
  6  where a.clan = '&&par_clan'
  7    and a.skills = 'Beginner'
  8  group by a.clan
  9  union all
 10  select listagg(result, ',')
 11  from (
 12    -- same query as above, with minor changes in WHERE clause
 13    select a.clan ||'-'||
 14           listagg(distinct b.wpncode, ',') ||'[' ||
 15           listagg(distinct c.wpncode, ',') ||']' as result
 16    from test a left join test b on a.clan = b.clan and b.skills = 'Archery'
 17                left join test c on c.clan = a.clan and c.skills = 'Powershot'
 18    where a.clan <> '&&par_clan'
 19      and a.skills <> 'Beginner'
 20    group by a.clan
 21    -- end of same query
 22    );
Enter value for par_clan: Daredevil

RESULT
--------------------------------------------------------------------------------
Daredevil-Archaccy,Archblst[Cannon,Rifle]
Bluesy-Bluearch,Greenarch[Knife,Torch],Stargaze-[Magnum,Pistol]

SQL>
© www.soinside.com 2019 - 2024. All rights reserved.