Une solution utilisant une fonction d'agrégation définie par l'utilisateur pour obtenir l'intersection de plusieurs collections :
Configuration d'Oracle :
Tout d'abord, définissez une collection pour contenir les workflows :
CREATE OR REPLACE TYPE VARCHAR2s_Table IS TABLE OF VARCHAR2(4000);
/
Deuxièmement, définissez un objet à utiliser dans le processus d'agrégation :
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;
/
Troisièmement, créez une fonction d'agrégation définie par l'utilisateur :
CREATE FUNCTION MULTISET_INTERSECT( collection VARCHAR2s_Table )
RETURN VARCHAR2s_Table
PARALLEL_ENABLE AGGREGATE USING Varchar2sTableIntersection;
/
Requête 1 - Sortie sous forme de collection :
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
);
Sortie :
COMMON_WORKFLOWS
----------------------
VARCHAR2S_TABLE( 'B' )
Requête 2 – Sortie sous forme de lignes :
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;
Sortie :
COMMON_WORKFLOWS
----------------
B