I have a table with a collection type in it. I want to SELECT
from the table and GROUP BY
some column. I want the results for each group to include a collection that contains the distinct union of all the individual collections in the group.
我有一个包含集合类型的表。我想从表和GROUP BY中选择一些列。我希望每个组的结果都包含一个集合,该集合包含组中所有单个集合的不同并集。
For example,
例如,
CREATE OR REPLACE TYPE my_varchar2_list AS TABLE OF VARCHAR2 (80);
WITH test_data (id, a_list) AS
(SELECT 1,
NEW my_varchar2_list ('A', 'B', 'C')
FROM DUAL
UNION ALL
SELECT 1,
NEW my_varchar2_list ('C', 'D', 'E')
FROM DUAL)
SELECT id,
... some magic syntax here...
FROM test_data
GROUP BY id
Desired results:
1, ('A','B','C','D','E')
What I am looking for in an answer
I am only looking for expressions that I can plug into the "magic syntax goes here" placeholder above. I know I can accomplish the aggregate by joining TABLE(a_list)
to the main table or otherwise restructuring my query (or, of course, using PL/SQL). Please don't bother to provide answers along those lines: they don't answer my question.
我只是寻找表达式,我可以插入上面的“magic syntax goes here”占位符。我知道我可以通过将TABLE(a_list)连接到主表或以其他方式重构我的查询(或者当然,使用PL / SQL)来完成聚合。请不要在这些方面提供答案:他们不回答我的问题。
1 个解决方案
#1
3
Adapted from my answer to another question.
改编自我对另一个问题的回答。
Oracle Setup:
Oracle安装程序:
CREATE OR REPLACE TYPE VARCHAR2s_Table IS TABLE OF VARCHAR2(100);
/
Create a user-defined aggregation type:
创建用户定义的聚合类型:
CREATE OR REPLACE TYPE Varchar2sTableUnion AS OBJECT(
list VARCHAR2s_Table,
STATIC FUNCTION ODCIAggregateInitialize(
ctx IN OUT Varchar2sTableUnion
) RETURN NUMBER,
MEMBER FUNCTION ODCIAggregateIterate(
self IN OUT Varchar2sTableUnion,
value IN VARCHAR2s_Table
) RETURN NUMBER,
MEMBER FUNCTION ODCIAggregateTerminate(
self IN OUT Varchar2sTableUnion,
returnValue OUT VARCHAR2s_Table,
flags IN NUMBER
) RETURN NUMBER,
MEMBER FUNCTION ODCIAggregateMerge(
self IN OUT Varchar2sTableUnion,
ctx IN OUT Varchar2sTableUnion
) RETURN NUMBER
);
/
CREATE OR REPLACE TYPE BODY Varchar2sTableUnion
IS
STATIC FUNCTION ODCIAggregateInitialize(
ctx IN OUT Varchar2sTableUnion
) RETURN NUMBER
IS
BEGIN
ctx := Varchar2sTableUnion( NULL );
RETURN ODCIConst.SUCCESS;
END;
MEMBER FUNCTION ODCIAggregateIterate(
self IN OUT Varchar2sTableUnion,
value IN VARCHAR2s_Table
) RETURN NUMBER
IS
BEGIN
IF value IS NULL THEN
NULL;
ELSIF self.list IS NULL THEN
self.list := value;
ELSE
self.list := self.list MULTISET UNION DISTINCT value;
END IF;
RETURN ODCIConst.SUCCESS;
END;
MEMBER FUNCTION ODCIAggregateTerminate(
self IN OUT Varchar2sTableUnion,
returnValue OUT VARCHAR2s_Table,
flags IN NUMBER
) RETURN NUMBER
IS
BEGIN
returnValue := self.list;
RETURN ODCIConst.SUCCESS;
END;
MEMBER FUNCTION ODCIAggregateMerge(
self IN OUT Varchar2sTableUnion,
ctx IN OUT Varchar2sTableUnion
) RETURN NUMBER
IS
BEGIN
IF self.list IS NULL THEN
self.list := ctx.list;
ELSIF ctx.list IS NULL THEN
NULL;
ELSE
self.list := self.list MULTISET UNION DISTINCT ctx.list;
END IF;
RETURN ODCIConst.SUCCESS;
END;
END;
/
Create a user-defined aggregation function:
创建用户定义的聚合函数:
CREATE FUNCTION MULTISET_UNION( list VARCHAR2s_Table )
RETURN VARCHAR2s_Table
PARALLEL_ENABLE AGGREGATE USING Varchar2sTableUnion;
/
Query:
查询:
Then you can just use it to perform the aggregation in your query:
然后,您可以使用它在查询中执行聚合:
WITH test_data (id, a_list) AS
(SELECT 1,
varchar2s_table ('A', 'B', 'C')
FROM DUAL
UNION ALL
SELECT 1,
varchar2s_table ('C', 'D', 'E')
FROM DUAL)
SELECT id,
MULTISET_UNION( a_list )
FROM test_data
GROUP BY id
Output:
输出:
ID MULTISET_UNION(A_LIST)
-- -------------------------------------------
1 SCHEMA.VARCHAR2S_TABLE('A','B','C','D','E')
#1
3
Adapted from my answer to another question.
改编自我对另一个问题的回答。
Oracle Setup:
Oracle安装程序:
CREATE OR REPLACE TYPE VARCHAR2s_Table IS TABLE OF VARCHAR2(100);
/
Create a user-defined aggregation type:
创建用户定义的聚合类型:
CREATE OR REPLACE TYPE Varchar2sTableUnion AS OBJECT(
list VARCHAR2s_Table,
STATIC FUNCTION ODCIAggregateInitialize(
ctx IN OUT Varchar2sTableUnion
) RETURN NUMBER,
MEMBER FUNCTION ODCIAggregateIterate(
self IN OUT Varchar2sTableUnion,
value IN VARCHAR2s_Table
) RETURN NUMBER,
MEMBER FUNCTION ODCIAggregateTerminate(
self IN OUT Varchar2sTableUnion,
returnValue OUT VARCHAR2s_Table,
flags IN NUMBER
) RETURN NUMBER,
MEMBER FUNCTION ODCIAggregateMerge(
self IN OUT Varchar2sTableUnion,
ctx IN OUT Varchar2sTableUnion
) RETURN NUMBER
);
/
CREATE OR REPLACE TYPE BODY Varchar2sTableUnion
IS
STATIC FUNCTION ODCIAggregateInitialize(
ctx IN OUT Varchar2sTableUnion
) RETURN NUMBER
IS
BEGIN
ctx := Varchar2sTableUnion( NULL );
RETURN ODCIConst.SUCCESS;
END;
MEMBER FUNCTION ODCIAggregateIterate(
self IN OUT Varchar2sTableUnion,
value IN VARCHAR2s_Table
) RETURN NUMBER
IS
BEGIN
IF value IS NULL THEN
NULL;
ELSIF self.list IS NULL THEN
self.list := value;
ELSE
self.list := self.list MULTISET UNION DISTINCT value;
END IF;
RETURN ODCIConst.SUCCESS;
END;
MEMBER FUNCTION ODCIAggregateTerminate(
self IN OUT Varchar2sTableUnion,
returnValue OUT VARCHAR2s_Table,
flags IN NUMBER
) RETURN NUMBER
IS
BEGIN
returnValue := self.list;
RETURN ODCIConst.SUCCESS;
END;
MEMBER FUNCTION ODCIAggregateMerge(
self IN OUT Varchar2sTableUnion,
ctx IN OUT Varchar2sTableUnion
) RETURN NUMBER
IS
BEGIN
IF self.list IS NULL THEN
self.list := ctx.list;
ELSIF ctx.list IS NULL THEN
NULL;
ELSE
self.list := self.list MULTISET UNION DISTINCT ctx.list;
END IF;
RETURN ODCIConst.SUCCESS;
END;
END;
/
Create a user-defined aggregation function:
创建用户定义的聚合函数:
CREATE FUNCTION MULTISET_UNION( list VARCHAR2s_Table )
RETURN VARCHAR2s_Table
PARALLEL_ENABLE AGGREGATE USING Varchar2sTableUnion;
/
Query:
查询:
Then you can just use it to perform the aggregation in your query:
然后,您可以使用它在查询中执行聚合:
WITH test_data (id, a_list) AS
(SELECT 1,
varchar2s_table ('A', 'B', 'C')
FROM DUAL
UNION ALL
SELECT 1,
varchar2s_table ('C', 'D', 'E')
FROM DUAL)
SELECT id,
MULTISET_UNION( a_list )
FROM test_data
GROUP BY id
Output:
输出:
ID MULTISET_UNION(A_LIST)
-- -------------------------------------------
1 SCHEMA.VARCHAR2S_TABLE('A','B','C','D','E')