我认为聚合的 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