我有一个db模式,看起来像这样:
create table user (id int, name varchar(32));
create table group (id int, name varchar(32));
create table group_member (group_id int, user_id int, flag int);
我想编写一个允许我这样做的查询:
给定有效的用户ID(UID),获取与指定用户ID(UID)在同一组中的所有用户的ID,并且group_member.flag = 3。
而不仅仅是拥有SQL。我想学习如何像Db程序员一样思考。作为一名程序员,SQL是我最薄弱的环节(因为我对命令式语言比对声明性语言更为满意) - 但我想改变它。
无论如何,这里是我确定的必要步骤来分解任务。如果一些SQL专家可以演示简单的SQL语句(即原子SQL语句,下面是每个已识别的子任务一个语句),最后我将如何组合这些语句来制作实现所需功能的ONE语句,我将不胜感激。
这里(假设指定的user_id [UID] = 1):
//Subtask #1.
Fetch list of all groups of which I am a member
Select group.id from user inner join group_member where user.id=group_member.user_id and user.id=1
//Subtask #2
Fetch a list of all members who are members of the groups I am a member of (i.e. groups in subtask #1)
Not sure about this ...
select user.id from user, group_member gm1, group_member gm2, ... [Stuck]
//Subtask #3
Get list of users that satisfy criteria group_member.flag=3
Select user.id from user inner join group_member where user.id=group_member.user_id and user.id=1 and group_member.flag=3
一旦我获得了subask2的SQL,我就会想看看如何从这些子任务构建完整的SQL语句(你不必在子任务中使用SQL,它只是解释所涉及的步骤的一种方式 - 另外,我的SQL可能不正确/效率低下,如果是这样,请随时纠正它,并指出它有什么问题。)
由于
答案 0 :(得分:6)
查询1 - 选择我所属的所有群组。
除非您还想要群组的名称,否则您不需要加入此处。只需查看group_member
表格。
SELECT group_id
FROM group_member
WHERE user_id = 1
结果:
1
3
查询2 :选择与我在同一组中的所有用户。
您可以自行加入group_member表以查找彼此位于同一组中的所有用户,然后添加where子句以仅查找与您自己位于同一组中的所有用户。添加DISTINCT
以确保您不会让人们两次。
SELECT DISTINCT T2.user_id
FROM group_member AS T1
JOIN group_member AS T2
ON T1.group_id = T2.group_id
WHERE T1.user_id = 1
AND T2.user_id <> 1 -- Remove myself
结果:
2
3
5
查询3 :在任何群组中都有标记3的用户。
您只需要查看group_member
表。如果您只想查看每个用户一次,请再次添加DISTINCT
。
SELECT DISTINCT user_id
FROM group_member
WHERE group_member.flag=3
结果:
2
3
4
最终查询:与我有同一组的用户,拥有标记3。
这与查询2几乎相同,只需添加一个额外的WHERE条件。
SELECT DISTINCT T2.user_id
FROM group_member AS T1
JOIN group_member AS T2
ON T1.group_id = T2.group_id
WHERE T1.user_id = 1
AND T2.user_id <> 1 -- Remove myself
AND T2.flag = 3
结果:
2
3
测试数据:
create table user (id int, name varchar(32));
create table `group` (id int, name varchar(32));
create table group_member (group_id int, user_id int, flag int);
insert into user (id, name) VALUES (1, 'user1'), (2, 'user2'), (3, 'user3'), (4, 'user4'), (5, 'user5');
insert into `group` (id, name) VALUES (1, 'group1'),(2, 'group2'), (3, 'group3');
insert into group_member (group_id, user_id, flag) VALUES (1, 1, 0), (1, 2, 3), (1, 3, 3), (2, 3, 3), (2, 4, 3), (2, 5, 0), (3, 1, 0), (3, 5, 0);
答案 1 :(得分:2)
这应该找到具有指定标志的特定用户所在的同一组中的所有人。
SELECT DISTINCT g2.user_id
FROM group_member AS g INNER JOIN group_member AS g2
ON g.group_id = g2.group_id
WHERE g.user_id = <the userid you want to find>
AND g2.flag = 3
为了解决这个问题,我做了以下几点:
我们需要比较两个group_member
,因为我们想要知道哪些属于同一组,因此我们需要将group_member
与自己联系起来。 (在group_id
上,因为我们想要同一组中的那些。)
我想确保其中一个是我要比较的用户,然后另一个必须有正确的标记。
完成此操作后,我只需从我与原始用户比较的user_id
中取出DISTINCT
即可。由于我认为用户可能在另外一个用户所在的两个组中,因此添加user_id
也可能是明智之举,以确保我们只从其中获取每个{{1}}一次。
答案 2 :(得分:-1)
SQL的优点在于,您可以将这三个选项与一个有效的连接一起加入。在这种情况下,我使用了WHERE版本的连接,因为我发现它更容易理解。但是你也可以看一下LEFT JOIN和INNER JOIN的语法,因为它们会给你很多表现力。
SELECT * FROM user, group_member, group
WHERE user.id = group_member.user_id
&& group_member.group_id = group.id
&& group_member.flag = 3