从 N:M 关系中获取给定组的成员

gue*_*tli 4 postgresql join many-to-many

我有这种 N:M 关系:

CREATE TABLE auth_user (
    id integer NOT NULL PRIMARY KEY,
    username character varying(150) NOT NULL UNIQUE
);

CREATE TABLE auth_group (
    id integer NOT NULL PRIMARY KEY,
    name character varying(80) NOT NULL UNIQUE
);

CREATE TABLE auth_user_groups (
    id integer NOT NULL PRIMARY KEY,
    user_id integer REFERENCES auth_user(id) NOT NULL,
    group_id integer REFERENCES auth_group(id) NOT NULL,
    CONSTRAINT user_groups UNIQUE(user_id, group_id)
);

INSERT INTO auth_user VALUES (1, 'user1');
INSERT INTO auth_user VALUES (2, 'user2');
INSERT INTO auth_group VALUES (1, 'group1');
INSERT INTO auth_group VALUES (2, 'group2');
INSERT INTO auth_user_groups VALUES (1, 1, 1);
INSERT INTO auth_user_groups VALUES (2, 2, 1);
INSERT INTO auth_user_groups VALUES (3, 2, 2);
Run Code Online (Sandbox Code Playgroud)

如何选择“group1”组中的所有用户名?

我使用 PostgreSQL,但首选可以在任何地方使用的 SQL。

Erw*_*ter 8

EXISTS无论 中是否存在重复条目,此查询都会返回唯一用户auth_user_groups

SELECT *
FROM   auth_user u
WHERE  EXISTS (
   SELECT 1
   FROM   auth_user_groups
   WHERE  user_id = u.id
   AND    group_id = (SELECT id FROM auth_group WHERE name = 'group1')
   );
Run Code Online (Sandbox Code Playgroud)

通常也很快。

笔记

对于 Postgres - 您似乎正在使用它。

索引列的顺序很重要。您定义了UNIQUE(user_id, group_id),这是使用相应的唯一索引实现的。对于您的特定查询,(group_id, user_id)最好使用索引。

您可以切换UNIQUE约束的列,也可以创建一个附加的(可选的唯一)索引,如果您需要同时反转列(这是常见情况)。有关的:

另请注意,UNIQUE约束中包含的列仍然可以是NULL. (不像PRIMARY KEY约束,这使得所有成员列NOT NULL自动!)你通常希望user_idgroup_idauth_user_groups成为NOT NULL为好。有关的:


a_h*_*ame 6

像这样的东西:

select *
from auth_user
where id in (select aug.user_id
             from auth_group ag
               join auth_user_groups aug on aug.group_id = ag.id
             where ag.name = 'group1');
Run Code Online (Sandbox Code Playgroud)