SQL查询以选择包含用户拥有的所有ACL的行
假设我对数据具有以下表权限:SQL查询以选择包含用户拥有的所有ACL的行,sql,sql-server,oracle,Sql,Sql Server,Oracle,假设我对数据具有以下表权限: ID NAME OWNER_ID ACL_ID ACL_NAME -------------------------------------------------- 100 Entity_1 1 1 g1 100 Entity_1 2 2 g2 100 Entity_1 3 3 g3 200
ID NAME OWNER_ID ACL_ID ACL_NAME
--------------------------------------------------
100 Entity_1 1 1 g1
100 Entity_1 2 2 g2
100 Entity_1 3 3 g3
200 Entity_2 1 1 g1
200 Entity_2 2 2 g2
300 Entity_3 1 1 g1
300 Entity_3 2 2 g2
300 Entity_3 4 NULL NULL
400 Entity_4 1 1 g1
400 Entity_4 2 2 g2
400 Entity_4 3 3 g3
400 Entity_4 4 NULL NULL
500 Entity_5 4 NULL NULL
500 Entity_5 5 NULL NULL
500 Entity_5 6 NULL NULL
600 Entity_6 NULL NULL NULL
如何选择所有(ID、名称)记录,这些记录的ACL\u ID=NULL行都不存在,但所有者\u ID=NULL的行除外。在此特定示例中,我想选择3行:
- (100,实体_1)-因为所有3行都具有ACL_ID!=空(1,2,3)
- (200,实体_2)-因为所有2行都具有ACL_ID!=空(1,2)
- (600,实体_6)-因为所有者_ID=NULL
SELECT DISTINCT
EMPLOYEE.ID
,EMPLOYEE.NAME
, OWNERS.OWNER_ID as OWNER_ID
, GROUPS.GROUP_ID as ACL_ID
, GROUPS.NAME as ACL_NAME
from EMPLOYEE
inner join ENTITIES on ENTITIES.ENTITY_ID = ID
left outer join OWNERS on (OWNERS.ENTITY_ID = ID and OWNERS.OWNER_ID != 123)
left outer join GROUPS on OWNERS.OWNER_ID = GROUPS.GROUP_ID
where
ENTITIES.STATUS != 'D'
这是我关于Oracle的解决方案
SELECT DISTINCT
EMPLOYEE.ID
,EMPLOYEE.NAME
, OWNERS.OWNER_ID as OWNER_ID
, GROUPS.GROUP_ID as ACL_ID
, GROUPS.NAME as ACL_NAME
from EMPLOYEE
inner join ENTITIES on ENTITIES.ENTITY_ID = ID
left outer join OWNERS on (OWNERS.ENTITY_ID = ID and OWNERS.OWNER_ID != 123)
left outer join GROUPS on OWNERS.OWNER_ID = GROUPS.GROUP_ID
where ENTITIES.STATUS != 'D'
and EMPLOYEE.ID not in (select id from EMPLOYEE
where GROUPS.GROUP_ID is null
and OWNERS.OWNER_ID is not null);
您只需附加我先前答案中的内部子查询,就可以得到您的解决方案。尝试以下方法:
select s.id, s.name
from
(select id,name,max(coalesce(owner_id,-1)) owner_id, min(coalesce(acl_id,-1)) acl_id
from yourtable
group by id,name) as s
where s.owner_id = -1
or (s.owner_id > -1 and s.acl_id > -1)
我们使用COALESCE
将空值默认为-1(假设列是整数),然后获得每个唯一id name
组合的owner\u id
和acl\u id
的最小值。如果owner\u id
的最大值为-1,则owner列为null。同样,如果acl_id
的最小值为-1,则至少存在一个空值行。基于这两个条件,我们过滤列表以获得所需的id-name
对。注意,在本例中,我只是选择-1作为默认值,因为我假设您不使用负数作为ID。如果这样做,您可以选择一个合适的“不可能”值作为COALESCE
函数的默认值
这应该适用于SQL Server和Oracle。在where子句中使用简单筛选器:
with tab(ID,NAME,OWNER_ID,ACL_ID,ACL_NAME) as (
select 100, 'Entity_1', 1,1, 'g1' from dual union all
select 100, 'Entity_1', 2,2, 'g2' from dual union all
select 100, 'Entity_1', 3,3, 'g3' from dual union all
select 200, 'Entity_2', 1,1, 'g1' from dual union all
select 200, 'Entity_2', 2,2, 'g2' from dual union all
select 300, 'Entity_3', 1,1, 'g1' from dual union all
select 300, 'Entity_3', 2,2, 'g2' from dual union all
select 300, 'Entity_3', 4,NULL, NULL from dual union all
select 400, 'Entity_4', 1,1, 'g1' from dual union all
select 400, 'Entity_4', 2,2, 'g2' from dual union all
select 400, 'Entity_4', 3,3, 'g3' from dual union all
select 400, 'Entity_4', 4,NULL,NULL from dual union all
select 500, 'Entity_5', 4,NULL,NULL from dual union all
select 500, 'Entity_5', 5,NULL,NULL from dual union all
select 500, 'Entity_5', 6,NULL,NULL from dual union all
select 600, 'Entity_6', NULL,NULL,NULL from dual)
--------------------------------
---End of data preparation here
--------------------------------
select a.id, a.name
from tab a
where ((a.ACL_ID is not null and a.ACL_NAME is not NULL) or a.OWNER_ID is null)
and not exists (select 'x'
from tab b
where b.id = a.id
and (b.ACL_ID is null or b.ACL_NAME is null)
and b.owner_id is not null)
group by a.id, a.name;
输出:
ID NAME
------------
200 Entity_2
100 Entity_1
600 Entity_6
但我仍然想知道,如果有数据,你的逻辑是什么:
ID NAME OWNER_ID ACL_ID ACL_NAME
--------------------------------------------------
600 Entity_1 null null null
600 Entity_1 2 null null
???????示例是什么?您正在尝试获取ACL_ID=1的条目吗?为什么还要记录ACL_ID=NULL的条目?在这种情况下,空值意味着什么?请参阅我对问题的更新检查我的更新答案。该逻辑也将排除
owner\u id
null的行。非常感谢,但请参阅我对问题的更新question@shree.pat18:他确实要求省略owner\u id=null
记录。不,他没有。他写道“如何选择所有(ID、名称)记录,其中除了所有者ID=NULL的行之外,没有一行ACL\u ID=NULL。”事实上,他在预期输出中包括(600,实体6)。我的错,我误解了。非常感谢,但请看我对问题的更新。很抱歉,没有马上告诉你,没有问题。如果yourtable
实际上是一个查询结果,则只需将该查询放入子查询或公共表表达式(CTE)中,并为其指定别名yourtable
。其他任何事情都不需要改变。让我知道这是否有帮助。谢谢,工作如预期,非常明智的决定与联合!