集計された WM_CONCAT 関数は ORDER BY の影響を受けないと思います。
したがって、約束どおり、結果を並べ替えるカスタム集計。以前のバージョンでも使用できます。
-- A string table type to hold the values to concat. I limited it to 4000 because
-- of trouble with the driver I use. You should be able to change it to 32767, or
-- whatever is VARCHAR2's max size.
CREATE OR REPLACE TYPE TT_STRING as table of varchar2(4000);
-- An aggregate type for the concatenation. It uses the string table to
-- hold all values, and sorts it when you're done aggregating.
CREATE OR REPLACE TYPE AT_CONCATSORTED as object
(
V_ITEMS TT_STRING,
static function ODCIAggregateInitialize(
P_CONTEXT in out AT_CONCATSORTED)
return number,
member function ODCIAggregateIterate(
self in out AT_CONCATSORTED,
P_VALUE in varchar2)
return number,
member function ODCIAggregateTerminate(
self in AT_CONCATSORTED,
P_RESULT out varchar2,
P_FLAGS in number)
return number,
member function ODCIAggregateMerge(
self in out AT_CONCATSORTED,
P_CONTEXT in AT_CONCATSORTED)
return number
);
create or replace type body AT_CONCATSORTED is
static function ODCIAggregateInitialize(
P_CONTEXT in out AT_CONCATSORTED)
return number
is
begin
if P_CONTEXT is null then
P_CONTEXT := AT_CONCATSORTED(TT_STRING(''));
else
P_CONTEXT.V_ITEMS.delete;
end if;
return ODCIConst.Success;
end;
member function ODCIAggregateIterate(
self in out AT_CONCATSORTED,
P_VALUE in varchar2)
return number
is
begin
self.V_ITEMS.extend;
self.V_ITEMS(self.V_ITEMS.last) := P_VALUE;
return ODCIConst.Success;
end;
member function ODCIAggregateTerminate(
self in AT_CONCATSORTED,
P_RESULT out varchar2,
P_FLAGS in number)
return number
is
V_SORTEDITEMS TT_STRING;
begin
select
cast(multiset(select
*
from
table(self.V_ITEMS)
order by
1) as TT_STRING)
into
V_SORTEDITEMS
from
dual;
for i in V_SORTEDITEMS.first..V_SORTEDITEMS.last loop
P_RESULT := P_RESULT || V_SORTEDITEMS(i);
if i < V_SORTEDITEMS.last - 1 then
P_RESULT := P_RESULT || ', ';
end if;
end loop;
return ODCIConst.Success;
end;
member function ODCIAggregateMerge(
self in out AT_CONCATSORTED,
P_CONTEXT in AT_CONCATSORTED)
return number
is
begin
for i in P_CONTEXT.V_ITEMS.first..P_CONTEXT.V_ITEMS.last loop
self.V_ITEMS.extend;
self.V_ITEMS(self.V_ITEMS.last) := P_CONTEXT.V_ITEMS(i);
end loop;
return ODCIConst.Success;
end;
end;
-- The actual concat function
create or replace function CONCATSORTED (input varchar2) return varchar2
aggregate using AT_CONCATSORTED;
クエリは次のようになります。
SELECT
V.PROJECTID,
CONCATSORTED(DISTINCT NAME) as NAMES
FROM
TPM_TRAININGPLAN JOIN TPM_DELIVERYMETHODS USING (METHODID)
WHERE
PROJECTID=V.PROJECTID
AND VERSIONID=V.VERSIONID) as Methods
FROM
TPM_PROJECTVERSION V