我有三张桌子:
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 :(得分:1)
使用用户定义聚合函数获取多个集合的交集的解决方案:
Oracle安装程序:
首先,定义一个集合来保存工作流程:
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
答案 1 :(得分:0)
我通过这种方式获得所有使用数字的rols
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
答案 2 :(得分: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
);