我有以下数据样本。
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]
一定是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>