Sql 返回多列或近似值的子查询
我有一个有趣的问题,但是我不知道如何更好地表达它,而不是说我有一个需要返回多个列的子查询。当我尝试这样做时,PostgreSQL会抛出一个错误,所以虽然我的SQL在逻辑上看起来有点合理,但显然有更好的方法。我正试图将用户权限合并到一个表中(希望将其放入一个视图,甚至是某种“物化视图”)。这是我的桌子:Sql 返回多列或近似值的子查询,sql,postgresql,permissions,usergroups,Sql,Postgresql,Permissions,Usergroups,我有一个有趣的问题,但是我不知道如何更好地表达它,而不是说我有一个需要返回多个列的子查询。当我尝试这样做时,PostgreSQL会抛出一个错误,所以虽然我的SQL在逻辑上看起来有点合理,但显然有更好的方法。我正试图将用户权限合并到一个表中(希望将其放入一个视图,甚至是某种“物化视图”)。这是我的桌子: CREATE TABLE users ( user_id integer NOT NULL, username character varying(32) NOT NULL, pass
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
);
以及一些用于填充它们的数据:
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);
我试图做的是创建一个可以计算用户可能拥有的有效权限的查询。用户存储在(您猜到的)“Users”表中。“组”中的组,用户可能被分配到的任何组都在“用户组”中。最后,每个用户都可以拥有个人权限,这些权限应覆盖组权限-这些权限存储在“用户权限”中
我可以使用(是的,我知道这很难看)来查询所有这些信息:
以上数据将为我在WHERE子句中指定的任何用户提供有效权限。我想做的是创建一个物化视图,该视图仅在用户或组数据更改时更新,但在其他方面是静态的。这一点我知道怎么做没有问题-我遇到的问题是生成这个视图。我的想法是使用上面的查询,但是让它为“users”表中的每个用户运行,并创建一个“user\u id”列。因此,我的“有效权限”表如下所示:
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
…等等。我就是不知道如何将用户id添加到此结果并显示多行。我希望我已经提供了足够的信息,以便有人了解我正在尝试做什么。我意识到,一旦表按大小分组,最终这种方法可能会在性能方面变得相当昂贵,而这种解决方案似乎是我能够提出的缓解该问题的最佳解决方案
如果您想为测试目的重新创建示例数据(我刚刚在本地pg服务器上快速地重新构建了它,尽管它比相同概念适用的实际表简单得多)。+1用于使问题易于重现。+1用于DDL,但我希望密码真的是一个密码散列…明文密码怎么了=当然是散列的,我只是用简单的数据作为例子。
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
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