SQL查询以获取至少一个公共项

时间:2018-02-28 10:55:01

标签: sql sql-server database

我有3张桌子,

room (room_no

room_no_access (room_no, user_id

user (user_id

如果用户在room_no_access表格中记录room_nouser_id,则该用户无法访问上述会议室。

我们假设我是user表中的用户。现在我需要的是让与我共享至少一个公共房间访问权限的用户。

如何编写SQL来完成这项工作?如果没有循环,那就更好了。

示例:

rooms

room_1,
room_2,
room_3,

users

1,
2,
3,
4,

rooms_no_access

    [room_1, 4],
    [room_2, 3].
    [room_3, 3],
    [room_1, 3],

如果我是用户4 - >我可以访问room_2,room_3 那么谁是可以访问room_2或room_3的其他用户 它们是 - > 1,2

3 个答案:

答案 0 :(得分:0)

这是一种回到前面的方式,因为你可以容纳人们无法访问的房间,我们真的想要人们可以访问的房间。

我创建了一些测试数据:

--Test data
DECLARE @room TABLE (room_no INT);
INSERT INTO @room SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3;
DECLARE @user TABLE ([user_id] INT);
INSERT INTO @user SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3;
DECLARE @room_no_access TABLE (room_no INT, [user_id] INT);
INSERT INTO @room_no_access SELECT 1, 1;
INSERT INTO @room_no_access SELECT 3, 2;
INSERT INTO @room_no_access SELECT 1, 3;
INSERT INTO @room_no_access SELECT 2, 3;
INSERT INTO @room_no_access SELECT 3, 3;

...然后提出了这个问题:

--For each user find users with common access
--First find which rooms each user can access
WITH room_access AS (
    SELECT
        r.room_no,
        u.[user_id]
    FROM
        @room r
        CROSS JOIN @user u
        LEFT JOIN @room_no_access rn ON rn.room_no = r.room_no AND rn.[user_id] = u.[user_id]
    WHERE
        rn.[user_id] IS NULL)
SELECT DISTINCT
    u.[user_id],
    sa.[user_id] AS shared_access_user
FROM
    @user u
    LEFT JOIN room_access ra ON ra.[user_id] = u.[user_id]
    LEFT JOIN room_access sa ON sa.room_no = ra.room_no
WHERE
    sa.[user_id] != u.[user_id]; --Ignore self match

这对工作来说有点啰嗦,但很容易理解。

结果是:

user_id shared_access_user
1   2
2   1

因为在我的数据中,user_id#1和#2共享对2号房间的访问权限,但是user_id#3无法访问任何房间。

我正在为数据库中的每个用户返回结果,但您可以将其过滤为仅返回指定用户的结果吗?

答案 1 :(得分:0)

试试这个:

select distinct [user_id] from (
    --all rooms that can be accessed by at least one user
    select room_no, [USER_ID] from room cross join [user]
    except
    select room_no, [USER_ID] from room_no_access
) a where room_no in (
    -- rooms that I have access to
    select room_no from room
    except
    select room_no from room_no_access where [USER_ID] = /*my_user_id*/
)

答案 2 :(得分:0)

此选择与您共享访问权限的用户及其共享的房间。

set @you = 1;

select 
    others_access.user_id, 
    others_access.room_no
from 
  (select room_no, @you as user_id 
  from room r
  /* rooms that you have access */
  where not exists (
    select * from room_no_access rna
    where rna.room_no = r.room_no
    and rna.user_id = @you)) you_access
join  
  /* rooms that others have access */
  (select room_no, u.user_id
  from room r cross join user u
  where u.user_id <> @you
  and not exists (
    select * from room_no_access rna
    where rna.room_no = r.room_no
    and rna.user_id = u.user_id)) others_access
on you_access.room_no = others_access.room_no;

Here a DB Fiddle to play with