2017-02-03 3 views
0

У меня есть три таблицы:получить общие строки из одной таблицы с любым столбцом

CREATE TABLE workflow_roles (
    role_id NUMBER  PRIMARY KEY, 
    role_desc VARCHAR2(20) 
); 

CREATE TABLE tbl_workflow (
    workflow_id VARCHAR2(5) PRIMARY KEY, 
    workflow_desc VARCHAR2(20) 
); 

CREATE TABLE workflow_detail (
    role_id  NUMBER  REFERENCES workflow_roles(role_id), 
    workflow_id VARCHAR2(5) REFERENCES tbl_workflow(workflow_id) 
); 

Пусть говорят данные:

INSERT INTO workflow_roles 
    SELECT 1, 'Role 1' FROM DUAL UNION ALL 
    SELECT 2, 'Role 2' FROM DUAL; 

INSERT INTO tbl_workflow 
    SELECT 'A', 'Work A' FROM DUAL UNION ALL 
    SELECT 'B', 'Work B' FROM DUAL UNION ALL 
    SELECT 'C', 'Work C' FROM DUAL UNION ALL 
    SELECT 'D', 'Work D' FROM DUAL UNION ALL 

INSERT INTO workflow_detail 
    SELECT 1, 'A' FROM DUAL UNION ALL 
    SELECT 1, 'B' FROM DUAL UNION ALL 
    SELECT 2, 'B' FROM DUAL UNION ALL 
    SELECT 2, 'C' FROM DUAL; 

Роль «B» существует в оба рабочих процессах

Я хочу получить общие роли, которые существуют в выбранных рабочих процессах, т.е. он должен возвращать роль B только.

Я попытался следующие:

select * from workflow_roles where role_id in 
(
select role_id from workflow_detail where workflow_id in (1,2) 
); 

Но она возвращается все роли, назначенные данной рабочие процессы.

Как я могу это сделать?

+0

Пожалуйста ** [EDIT] ** ваш вопрос и добавить некоторые выборочные данные и ожидаемый результат на основе этих данных. [** Отформатированный текст **] (http://stackoverflow.com/help/formatting), пожалуйста, [скриншоты] (http://meta.stackoverflow.com/questions/285551/why-may-i-not -upload-images-of-code-on-so-when-ask-a-question/285557 # 285557) –

ответ

0

Я так у вас есть все РОЛС с номером они используются

select wr.role_desc role_desc, count(*) role_nums 
    from workflow_detail wd 
    inner join workflow_roles wr on wr.role_id = wd.role_id 
    inner join tbl_workflow tw on tw.workflow_id = wd.workflow_id 
    group by wr.role_desc 
    order by role_nums desc 

еще

Если вам нужна роль, которые являются общими между два процессом можно фильтровать особую роль, имеющей conut = 2

select wr.role_desc role_desc, count(disctinct wd.role_id) role_nums 
from workflow_detail wd 
inner join workflow_roles wr on wr.role_id = wd.role_id 
inner join tbl_workflow tw on tw.workflow_id = wd.workflow_id 
where wd.workflow_id in (1,2) 
group by wr.role_desc 
having role_nums = 2 
order by role_nums desc 
+0

Я хочу, чтобы те записи, которые одинаковы в таблице wokflow_detail, с workflow_id, –

0

Одно простое решение: вы хотите роль быть в двух сетах, поэтому запрос два множеств с IN:

select * from workflow_roles 
where role_id in (select role_id from workflow_detail where workflow_id = 1) 
    and role_id in (select role_id from workflow_detail where workflow_id = 2); 

Другим вариантом является подсчет совпадений в workflow_detail.Вы ищете два workflow_ids, поэтому проверьте ли вы найти два для роли:

select * from workflow_roles 
where role_id in 
(
    select role_id 
    from workflow_detail 
    where workflow_id in (1,2) 
    group by role_id 
    having count(distinct workflow_id) = 2 
); 
+0

, идентификатор рабочего процесса может быть кратным, я не могу пройти каждый идентификатор рабочего процесса отдельно –

+0

@Alina Anjum: Я понял ваш вопрос таким образом, что вы хотите найти все роли рабочего процесса, которые являются общими для всех рабочих процессов, которые вы хотите найти. Вы привели пример, где вы хотели посмотреть рабочие процессы 1 и 2 и найти все роли, которые находятся в обоих. Я не знаю, чего ты хочешь. Если вам нужно тридцать идентификаторов рабочих процессов от 4 до 33, вы просто сделаете это 'where workflow_id в (4,5,6,7, ..., 33)' и 'с count (different workflow_id) = 30'. Если это не то, что вы хотите, что еще вы хотите? –

1

Решения с использованием определенного пользователем функции агрегирования, чтобы получить пересечение нескольких семейств:

Oracle Setup :

Во-первых, определить набор для хранения рабочих процессов:

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

Во-вторых, определим Объект для использования в процессе агрегации:

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

В-третьих, создать определенную пользователем функцию агрегации:

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

запроса 1 - Вывод в виде коллекции:

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

Выход:

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

Запрос 2 - Выход в виде строк:

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; 

Выход:

COMMON_WORKFLOWS 
---------------- 
B 
Смежные вопросы