结合两个查询

时间:2011-02-02 11:38:13

标签: sql sql-server sql-server-2005 tsql

我有以下2个查询按预期工作:

declare @user varchar(3)
declare @phrase varchar(255)

set @user = 'xyz'
set @phrase = '%nav%'

select ug.*, wap.*, w.*
from user_groups ug
inner join widget_access_permissions wap on ug.id = wap.allowed
inner join widgets w on wap.widget_id = w.widget_id
where ug.employee_code = @user
and w.widget_name like @phrase

select w.widget_id, ug.*, wdp.*, w.*
from user_groups ug
inner join widget_deny_permissions wdp on ug.id = wdp.denied
inner join widgets w on wdp.widget_id = w.widget_id
where ug.employee_code = @user
and w.widget_name like @phrase

第一个查询显示@user根据提供的@phrase访问的任何小部件的记录。第二个查询显示@user根据提供的@phrase无权访问的任何小部件的记录。

如何将这两个查询合并为1,如果某人有基于某个组的访问权限,但因为他在另一个拒绝表中拒绝的组中,他就看不到结果?

我不知道我的最后一句话是否有意义......

编辑:添加了表名,表列和一些示例数据:

user_groups

table
id
display_value
employee_code
dept
persnl_typ_code

sample row 1
1000
group 1
xyz
i.t.
gen

sample row 2
1008
group 2
xyz
i.t.
gen

==========

widget_access_permissions

table
id
widget_id
allowed

sample row
0
0
1000

==========

widget_deny_permissons

table
id
widget_id
denied

sample row
0
0
1008

==========

widgets

table
widget_id
widget_name
widget_description
widget_header
widget_sub_header
widget_content

sample row
0
widget name goes here
widget description goes here
widget header goes here
widget sub header goes here
widget content goes here

3 个答案:

答案 0 :(得分:3)

简单的方法是使用子查询:

declare @user varchar(3)
declare @phrase varchar(255)

set @user = 'xyz'
set @phrase = '%nav%'

select ug.*, wap.*, w.*
from user_groups ug
inner join widget_access_permissions wap on ug.id = wap.allowed
inner join widgets w on wap.widget_id = w.widget_id
where ug.employee_code = @user
and w.widget_name like @phrase
and w.WidgetId not in (

select w.widget_id
from user_groups ug
inner join widget_deny_permissions wdp on ug.id = wdp.denied
inner join widgets w on wdp.widget_id = w.widget_id
where ug.employee_code = @user
and w.widget_name like @phrase
)

不确定性能如何。

编辑:

我认为您可以通过使用以下内容来删除子查询的需要:

declare @user varchar(3)
declare @phrase varchar(255)

set @user = 'xyz'
set @phrase = '%nav%'

select ug.*, wap.*, w.*
from user_groups ug
inner join widget_access_permissions wap on ug.id = wap.allowed
inner join widgets w on wap.widget_id = w.widget_id

Left Join widget_deny_permissions wdp on ug.id = wdp.denied
                        and w.widget_id = wdp.widget_id
where ug.employee_code = @user
and w.widget_name like @phrase
and wdp.Id Is Null

这取决于您的架构和数据

答案 1 :(得分:2)

如果我理解正确,你想要联合权限(最严格的方法),如果一个组允许用户而另一个组被拒绝,他应该得到那个小部件,如果是这种情况,你可以这样做,

declare @user varchar(3)
declare @phrase varchar(255)

set @user = 'xyz'
set @phrase = '%nav%'

select ug.*, wap.*, w.*
from user_groups ug
inner join widget_access_permissions wap on ug.id = wap.allowed
inner join widgets w on wap.widget_id = w.widget_id
where ug.employee_code = @user
and w.widget_name like @phrase
and w.widget_id NOT IN (
       select w.widget_id 
         from user_groups ug
         inner join widget_deny_permissions wdp on ug.id = wdp.denied
         inner join widgets w on wdp.widget_id = w.widget_id
         where ug.employee_code = @user
         and w.widget_name like @phrase
        )

答案 2 :(得分:2)

由于您使用的是SQL Server 2005,因此可以使用EXCEPT

select w.*
from user_groups ug
inner join widget_access_permissions wap on ug.id = wap.allowed
inner join widgets w on wap.widget_id = w.widget_id
where ug.employee_code = @user
and w.widget_name like @phrase
EXCEPT
select w.*
from user_groups ug
inner join widget_deny_permissions wdp on ug.id = wdp.denied
inner join widgets w on wdp.widget_id = w.widget_id
where ug.employee_code = @user
and w.widget_name like @phrase

这会获取第一个(允许)查询的结果,减去第二个(拒绝)查询的结果,只留下那些允许用户被拒绝的小部件。

注意我已更改了原始SELECT列表,因为EXCEPT要求两个查询(有效)具有相同的SELECT列表,在我看来,您感兴趣的是什么in是小部件。