Oracle
 sql >> Database >  >> RDS >> Oracle

ottenere righe comuni da una tabella rispetto a qualsiasi colonna

Una soluzione che utilizza una funzione di aggregazione definita dall'utente per ottenere l'intersezione di più raccolte:

Impostazione Oracle :

Innanzitutto, definisci una raccolta per contenere i flussi di lavoro:

CREATE OR REPLACE TYPE VARCHAR2s_Table IS TABLE OF VARCHAR2(4000);
/

In secondo luogo, definisci un oggetto da utilizzare nel processo di aggregazione:

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;
/

In terzo luogo, crea una funzione di aggregazione definita dall'utente:

CREATE FUNCTION MULTISET_INTERSECT( collection VARCHAR2s_Table )
RETURN VARCHAR2s_Table
PARALLEL_ENABLE AGGREGATE USING Varchar2sTableIntersection;
/

Query 1 - Output come raccolta :

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
);

Risultato :

COMMON_WORKFLOWS
----------------------
VARCHAR2S_TABLE( 'B' )

Query 2 - Output come righe :

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;

Risultato :

COMMON_WORKFLOWS
----------------
B