Uma solução usando uma função de agregação definida pelo usuário para obter a interseção de várias coleções:
Configuração do Oracle :
Primeiro, defina uma coleção para conter os fluxos de trabalho:
CREATE OR REPLACE TYPE VARCHAR2s_Table IS TABLE OF VARCHAR2(4000);
/
Em segundo lugar, defina um objeto para usar no processo de agregação:
CREATE OR REPLACE TYPE Varchar2sTableIntersection AS OBJECT(
intersection VARCHAR2s_Table,
STATIC FUNCTION ODCIAggregateInitialize(
ctx IN OUT Varchar2sTableIntersection
) RETURN NUMBER,
MEMBER FUNCTION ODCIAggregateIterate(
self IN OUT Varchar2sTableIntersection,
value IN VARCHAR2s_Table
) RETURN NUMBER,
MEMBER FUNCTION ODCIAggregateTerminate(
self IN OUT Varchar2sTableIntersection,
returnValue OUT VARCHAR2s_Table,
flags IN NUMBER
) RETURN NUMBER,
MEMBER FUNCTION ODCIAggregateMerge(
self IN OUT Varchar2sTableIntersection,
ctx IN OUT Varchar2sTableIntersection
) RETURN NUMBER
);
/
CREATE OR REPLACE TYPE BODY Varchar2sTableIntersection
IS
STATIC FUNCTION ODCIAggregateInitialize(
ctx IN OUT Varchar2sTableIntersection
) RETURN NUMBER
IS
BEGIN
ctx := Varchar2sTableIntersection( NULL );
RETURN ODCIConst.SUCCESS;
END;
MEMBER FUNCTION ODCIAggregateIterate(
self IN OUT Varchar2sTableIntersection,
value IN VARCHAR2s_Table
) RETURN NUMBER
IS
BEGIN
IF value IS NULL THEN
NULL;
ELSIF self.intersection IS NULL THEN
self.intersection := value;
ELSE
self.intersection := self.intersection MULTISET INTERSECT value;
END IF;
RETURN ODCIConst.SUCCESS;
END;
MEMBER FUNCTION ODCIAggregateTerminate(
self IN OUT Varchar2sTableIntersection,
returnValue OUT VARCHAR2s_Table,
flags IN NUMBER
) RETURN NUMBER
IS
BEGIN
returnValue := self.intersection;
RETURN ODCIConst.SUCCESS;
END;
MEMBER FUNCTION ODCIAggregateMerge(
self IN OUT Varchar2sTableIntersection,
ctx IN OUT Varchar2sTableIntersection
) RETURN NUMBER
IS
BEGIN
IF self.intersection IS NULL THEN
self.intersection := ctx.intersection;
ELSIF ctx.intersection IS NULL THEN
NULL;
ELSE
self.intersection := self.intersection MULTISET INTERSECT ctx.intersection;
END IF;
RETURN ODCIConst.SUCCESS;
END;
END;
/
Em terceiro lugar, crie uma função de agregação definida pelo usuário:
CREATE FUNCTION MULTISET_INTERSECT( collection VARCHAR2s_Table )
RETURN VARCHAR2s_Table
PARALLEL_ENABLE AGGREGATE USING Varchar2sTableIntersection;
/
Consulta 1 - Saída como uma coleção :
SELECT MULTISET_INTERSECT( workflows ) AS common_workflows
FROM (
SELECT role_id,
CAST(
COLLECT(
workflow_id
) AS VARCHAR2s_Table
) AS workflows
FROM workflow_detail
GROUP BY role_id
);
Saída :
COMMON_WORKFLOWS
----------------------
VARCHAR2S_TABLE( 'B' )
Consulta 2 - Saída como linhas :
SELECT t.COLUMN_VALUE AS common_workflows
FROM (
SELECT MULTISET_INTERSECT( workflows ) AS common
FROM (
SELECT role_id,
CAST(
COLLECT(
workflow_id
) AS VARCHAR2s_Table
) AS workflows
FROM workflow_detail
GROUP BY role_id
)
) cw
CROSS JOIN TABLE( cw.common ) t;
Saída :
COMMON_WORKFLOWS
----------------
B