子查询返回多列 - 或近似

rag*_*885 7 sql postgresql permissions usergroups

我有一个有趣的问题,但是我不知道如何更好地表达它比说我有一个需要返回多列的子查询.当我试图这样做时,PostgreSQL会抛出一个错误,所以虽然我的SQL在某种程度上听起来对我来说很明显 - 显然有一种更好的方法可以做到这一点.我正在尝试将用户权限合并到一个表中(希望将其放入视图或甚至是各种类型的"物化视图").这是我的表格:

CREATE TABLE users (
  user_id integer NOT NULL,
  username character varying(32) NOT NULL,
  passwd character varying(32) NOT NULL,
  dept_id integer NOT NULL,
  last_activity timestamp with time zone NOT NULL DEFAULT now(),
  CONSTRAINT "pk-users-user_id" PRIMARY KEY (user_id)
);

CREATE TABLE groups (
  group_id integer NOT NULL,
  group_name character varying(32) NOT NULL,
  add_posts integer NOT NULL DEFAULT 0,
  remove_posts integer NOT NULL DEFAULT 0,
  modify_users integer NOT NULL DEFAULT 0,
  add_users integer NOT NULL DEFAULT 0,
  delete_users integer NOT NULL DEFAULT 0,
  CONSTRAINT "pk-groups-group_id" PRIMARY KEY (group_id)
);

CREATE TABLE user_groups (
  user_id integer NOT NULL,
  group_id integer NOT NULL,
  CONSTRAINT "fk-user_groups-group_id" FOREIGN KEY (group_id)
      REFERENCES groups (group_id) MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE NO ACTION,
  CONSTRAINT "fk-user_groups-user_id" FOREIGN KEY (user_id)
      REFERENCES users (user_id) MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE NO ACTION
);

CREATE TABLE user_rights (
  user_id integer NOT NULL,
  add_posts integer NOT NULL DEFAULT 0,
  remove_posts integer NOT NULL DEFAULT 0,
  modify_users integer NOT NULL DEFAULT 0,
  add_users integer NOT NULL DEFAULT 0,
  delete_users integer NOT NULL DEFAULT 0,
  CONSTRAINT "fk-user_rights-user_id" FOREIGN KEY (user_id)
      REFERENCES users (user_id) MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE CASCADE
);
Run Code Online (Sandbox Code Playgroud)

以及一些填充它们的数据:

INSERT INTO users(user_id, username, passwd, dept_id) VALUES (1, 'nicole','123456',12);
INSERT INTO users(user_id, username, passwd, dept_id) VALUES (2, 'john','324634',11);
INSERT INTO users(user_id, username, passwd, dept_id) VALUES (3, 'susan','61236',14);
INSERT INTO users(user_id, username, passwd, dept_id) VALUES (4, 'mary','1213612',2);
INSERT INTO user_rights(user_id, add_posts, remove_posts, modify_users, add_users, delete_users) VALUES (1,0,0,1,1,1);
INSERT INTO user_rights(user_id, add_posts, remove_posts, modify_users, add_users, delete_users) VALUES (2,1,1,1,1,1);
INSERT INTO user_rights(user_id, add_posts, remove_posts, modify_users, add_users, delete_users) VALUES (3,0,0,0,0,0);
INSERT INTO user_rights(user_id, add_posts, remove_posts, modify_users, add_users, delete_users) VALUES (4,0,0,0,0,0);
INSERT INTO groups(group_id, group_name, add_posts, remove_posts, modify_users, add_users, delete_users) VALUES (1,'Poster',1,1,0,0,0);
INSERT INTO groups(group_id, group_name, add_posts, remove_posts, modify_users, add_users, delete_users) VALUES (2,'User Mgr',0,0,1,1,1);
INSERT INTO groups(group_id, group_name, add_posts, remove_posts, modify_users, add_users, delete_users) VALUES (3,'Admin',1,1,1,1,1);
INSERT INTO user_groups(user_id, group_id) VALUES (1,1);
INSERT INTO user_groups(user_id, group_id) VALUES (2,2);
INSERT INTO user_groups(user_id, group_id) VALUES (3,2);
INSERT INTO user_groups(user_id, group_id) VALUES (4,3);
INSERT INTO user_groups(user_id, group_id) VALUES (1,2);
Run Code Online (Sandbox Code Playgroud)

我要做的是创建一个可以计算用户可能拥有的有效权限的查询.用户存储在(您猜对了)'用户'表中."组"中的组,无论用户可能被分配到哪个组,都在"user_groups"中.最后,每个用户都可以拥有应该覆盖组权限的个人权限 - 这些权限存储在"user_rights"中.

我可以使用(并且是的,我知道这很丑陋)来查询所有这些信息:

select
  max(add_posts) as add_posts,
  max(remove_posts) as remove_posts,
  max(modify_users) as modify_users,
  max(add_users) as add_users,
  max(delete_users) as delete_users
from
(
select 
  max(add_posts) as add_posts,
  max(remove_posts) as remove_posts,
  max(modify_users) as modify_users,
  max(add_users) as add_users,
  max(delete_users) as delete_users
from
  groups
where
  group_id in (select group_id from user_groups where user_id = 3)
union all
select  
  max(add_posts) as add_posts,
  max(remove_posts) as remove_posts,
  max(modify_users) as modify_users,
  max(add_users) as add_users,
  max(delete_users) as delete_users
from 
  user_rights
where
  user_id = 3
) as combined_user_groups
Run Code Online (Sandbox Code Playgroud)

给出上述数据的哪些内容将为我在WHERE子句中指定的任何用户提供有效权限.我想要做的是创建一个物化视图,该视图仅在用户或组数据更改时更新,否则为静态.我知道如何处理没有问题 - 我遇到的问题是产生这个视图.我的想法是使用上面的查询 - 但让它在'users'表中为每个用户运行并创建'user_id'列.所以我的'effective_permissions'表看起来像这样:

user_id, add_posts, remove_posts, modify_users, add_users, delete_users
1        1          1             1             1          1
2        1          1             1             1          1
3        0          0             1             1          1
Run Code Online (Sandbox Code Playgroud)

..等等.我只是无法弄清楚如何将user_id添加到此结果并显示多行.我希望我已经为某人提供了足够的信息,以便了解我正在尝试做什么.我意识到,一旦表格分组大小,这种方法最终会变得相当昂贵 - 而且这个解决方案似乎是我能提出的最好的方法来缓解这个问题.

如果你想重新创建用于测试目的的示例数据,那么提供的示例应该可行(我只是在我的本地pg服务器上快速重建它,尽管它比真正的表更简单,相同的概念适用).

Pau*_*sey 2

select
  user_id
  max(add_posts) as add_posts,
  max(remove_posts) as remove_posts,
  max(modify_users) as modify_users,
  max(add_users) as add_users,
  max(delete_users) as delete_users
from
(
select 
  ug.user_id
  max(g.add_posts) as add_posts,
  max(g.remove_posts) as remove_posts,
  max(g.modify_users) as modify_users,
  max(g.add_users) as add_users,
  max(g.delete_users) as delete_users
from
  groups g
inner join
  users_groups ug
on g.group_id = ug.group_id
group by    
  ug.user_id
union
select
  user_id  
  max(add_posts) as add_posts,
  max(remove_posts) as remove_posts,
  max(modify_users) as modify_users,
  max(add_users) as add_users,
  max(delete_users) as delete_users
from 
  user_rights
group by
  user_id
) as combined_user_groups
group by
  user_id
Run Code Online (Sandbox Code Playgroud)