如何使用 JOIN 而不是 IN 来选择一个人所属的所有组的名称?
考虑以下简化示例:
CREATE TABLE groups ( gid INTEGER PRIMARY KEY, name VARCHAR(100) );
CREATE TABLE people ( pid INTEGER PRIMARY KEY );
CREATE TABLE people_groups (
gid INTEGER NOT NULL
CONSTRAINT fk_people_groups_group
REFERENCES groups(gid),
pid INTEGER NOT NULL
CONSTRAINT fk_people_groups_person
REFERENCES people(pid),
CONSTRAINT pk_people_groups PRIMARY KEY (gid, pid)
);
INSERT INTO people (pid) VALUES (1);
INSERT INTO groups (gid, name) VALUES (1, 'One');
INSERT INTO groups (gid, name) VALUES (2, 'Two');
INSERT INTO people_groups (gid, pid) VALUES (1,1);
INSERT INTO people_groups (gid, pid) VALUES (2,1);
SELECT gid, name FROM groups WHERE gid IN (
SELECT gid FROM people_groups WHERE pid = 1
);
此输出:
1|One 2|Two
最后一个 SELECT
的正确 JOIN
是什么?
Consider the following simplified example:
CREATE TABLE groups ( gid INTEGER PRIMARY KEY, name VARCHAR(100) );
CREATE TABLE people ( pid INTEGER PRIMARY KEY );
CREATE TABLE people_groups (
gid INTEGER NOT NULL
CONSTRAINT fk_people_groups_group
REFERENCES groups(gid),
pid INTEGER NOT NULL
CONSTRAINT fk_people_groups_person
REFERENCES people(pid),
CONSTRAINT pk_people_groups PRIMARY KEY (gid, pid)
);
INSERT INTO people (pid) VALUES (1);
INSERT INTO groups (gid, name) VALUES (1, 'One');
INSERT INTO groups (gid, name) VALUES (2, 'Two');
INSERT INTO people_groups (gid, pid) VALUES (1,1);
INSERT INTO people_groups (gid, pid) VALUES (2,1);
SELECT gid, name FROM groups WHERE gid IN (
SELECT gid FROM people_groups WHERE pid = 1
);
This outputs:
1|One 2|Two
What is the correct JOIN
for that last SELECT
?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
注意:这相当于您的
IN
语句,因为您专门过滤了一个人。如果您过滤多个人,情况就会有所不同。例如,假设pid=2
的某个人也在组 1 中,并且您执行以下 SELECT:这将返回组 1 两次(与您的
IN
解决方案相反) ,这只会返回每个组一次)。要解决这个问题,您需要在SELECT
后添加DISTINCT
关键字或添加GROUP BY g.gid, g.name< /code> 在 SQL 的最后。如果您使用此答案作为将
IN
转换为JOIN
的一般规则,您应该记住这一点。Note: This is equivalent to your
IN
statement, because you specifically filter for only one person. If you filter for multiple persons, things are different. For example, assume that some person withpid=2
is also in group 1 and you do the following SELECT:This would return group 1 twice (in contrast to your
IN
solution, which would return each group only once). To solve this, you need to add theDISTINCT
keyword after theSELECT
or addGROUP BY g.gid, g.name
at the very end of the SQL. You should keep that in mind if you use this answer as a general rule to convertIN
toJOIN
.这是等价的:
This is the equivalent:
怎么样:
How about:
之前给出的答案是正确的,但我想指出,您的查询将从在
(pid, gid)
(按此顺序)上创建PRIMARY KEY
中受益。此查询:
然后能够使
people_groups
在JOIN
中处于领先地位,这很可能会使速度更快,因为pid
似乎是在链接表中非常有选择性。或者,您可以创建辅助索引:
,或者仅
当
people_groups
为InnoDB
时创建。The answers given before are correct, but I'd like to note that you query will benefit from making the
PRIMARY KEY
on(pid, gid)
(in this order).This query:
will then be able to make
people_groups
be leading in theJOIN
which most probably will make it much faster, sincepid
seems to be very selective in the link table.Alternatively, you can create a secondary index:
, or just
if
people_groups
isInnoDB
.