因此,假设我正在尝试获取属于某个用户组的所有用户的列表。易:
SELECT *
FROM users, usergroups
WHERE usergroups.user_group_id = 1
现在,假设我想获得一个属于某个用户组的所有用户的列表,以及一封以.edu结尾的电子邮件。
SELECT *
FROM users, usergroups
WHERE usergroups.user_group_id = 1
AND users.email LIKE '%.edu'
这很有效。现在假设我们想要获得上述所有内容以及属于用户组2的用户 - 但我们并不关心第二组的电子邮件地址。此查询不起作用:
SELECT *
FROM users, usergroups
WHERE usergroups.user_group_id IN (1,2)
AND users.email LIKE '%.edu'
因为它会过滤第二组中的用户。现在我正在做这样的事情:
SELECT *
FROM users as usrs, usergroups as groups1, usergroups as groups2
WHERE (groups1s.user_group_id = 1 AND users.email LIKE '%.edu')
OR groups2.user_group_id = 2
这给了我想要的结果,但我讨厌它看起来和工作的方式。有更清洁的方法吗?
修改
我没有在上一次迭代中包含联接。以下是查询的真实含义:
SELECT *
FROM users as usrs JOIN
usergroups as groups1 on usrs.group_id = groups1.group_id JOIN
usergroups as groups2 on usrs.group_id = groups2.group_id
WHERE (groups1.user_group_id = 1 AND users.email LIKE '%.edu')
OR groups2.user_group_id = 2
答案 0 :(得分:5)
不需要使用不同的别名选择两次用户组。你可以做到:
SELECT *
FROM users as usrs, usergroups
WHERE (usergroups.user_group_id = 1 AND users.email LIKE '%.edu')
OR usergroups.user_group_id = 2
或者,甚至更好(使用加入):
SELECT *
FROM users as usrs
JOIN usergroups on usergroups.userid = users.id
WHERE (usergroups.user_group_id = 1 AND users.email LIKE '%.edu')
OR usergroups.user_group_id = 2
答案 1 :(得分:2)
由于SQL语法,你正在做的事情可能会起作用,即使它看起来很丑陋。对我没有意义的是为什么用户ID上的用户和用户组之间没有连接:
...其中usergroups.user_id = users.user_id
除非我遗漏了某些内容,因为您正在进行用户和用户组之间的交叉连接。如果你列出每个表中的列,它会帮助我们一大堆。
答案 2 :(得分:2)
我会稍微考虑一下,并假设用户和用户组之间存在关系。然后你就像这样编写你的查询:
SELECT *
FROM users as usrs
INNER JOIN usergroups as groups1
ON usrs.GroupID = groups1.GroupID
WHERE (groups1.user_group_id = 1 AND usrs.email LIKE '%.edu')
OR groups1.user_group_id = 2
答案 3 :(得分:1)
修复你的JOIN。
对于用户组中的每个行,您总是从用户返回每个行(暂时忽略电子邮件过滤器),因为您没有JOIN,无论他们属于哪个组至。你有一个简单的交叉加入/笛卡儿产品。
然后,使用UNION或UNION ALL删除OR。或者将OR留在原地。
SELECT *
FROM
users as usrs
JOIN
usergroups as groups1 ON usrs.foo = groups1.foo
WHERE
groups1s.user_group_id = 1 AND users.email LIKE '%.edu'
UNION --maybe UNION ALL
SELECT *
FROM
users as usrs
JOIN
usergroups as group2 ON usrs.foo = groups2.foo
WHERE
groups2.user_group_id = 2
答案 4 :(得分:1)
关于Michael Goldshteyn所说的关于使用JOINS重新编写它的内容,以及Joe Stefnelli关于交叉连接的评论,您的初始查询将被重写:
SELECT *
FROM users
JOIN user_groups ON users.user_group_id = user_groups.user_group_id
WHERE users.email LIKE '%.edu'
AND user_groups.user_group_id = 1
添加第二组将导致:
SELECT *
FROM users AS users
JOIN user_groups AS user_groups ON users.user_group_id = user_groups_1.user_group_id
WHERE ( ( users.email LIKE '%.edu' AND user_groups_1.user_group_id = 1 )
OR user_groups_2.user_group_id = 2 )
或者你甚至可以做一个工会(我个人不会这样做):
SELECT *
FROM users AS users_1
JOIN user_groups AS user_groups_1 ON users_1.user_group_id = user_groups_1.user_group_id
WHERE users_1.email LIKE '%.edu'
AND user_groups_1.user_group_id = 1
UNION
SELECT *
FROM users AS users_2
JOIN user_groups AS user_groups_2 ON users_2.user_group_id = user_groups_2.user_group_id
AND user_groups_2.user_group_id = 2
答案 5 :(得分:1)
我发现你的最新编辑没有任何问题。你可以做一个Union
,但我认为这将是更加丑陋的。
答案 6 :(得分:1)
对于大型表格(可能不是这种情况),您应该考虑查询可能带来的性能损失。所以我更喜欢以下方法:首先我选择一些临时表我要使用的行,然后我删除不需要的行,最后我选择结果集并删除内存中的对象。注意:此查询使用 Transact SQL 。
select u.*, g.user_group_id into #TEMP from users u, usergroups g where u.group_id = g.group_id and g.user_group_id in (1,2)
delete from #TEMP where user_group_id = 1 and email not like '%.edu'
select * from #TEMP
drop table #TEMP