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

现在我使用SQL Server,但如果可能的话,我希望它也能在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'

这是我关于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
。其他任何事情都不需要改变。让我知道这是否有帮助。谢谢,工作如预期,非常明智的决定与联合!