我有这 3 个表:
create table reports(id int not null AUTO_INCREMENT,name varchar(255)not null,public_access tinyint not null,primary key (id)); create table report_users(id int not null AUTO_INCREMENT,report_id int not null,user_id int not null,primary key (id),foreign key (report_id) references reports(id)); create table report_groups(id int not null AUTO_INCREMENT,report_id int not null,group_id int not null,primary key (id),foreign key (report_id) references reports(id));
我想从报告表中获取至少满足以下条件之一的行:
1 - The field public_access is true 2 - The report is in the related table report_users with in parameter user_id 3 - The report is in the related table report_groups with in parameter group_id
首先,我创建一个可公开访问的新报告:
insert into reports values(null, 'report 1 open to all', 1);
然后另一个报告只能由 user_id = 1 访问:
insert into reports values(null, 'report 2 only for user_id 1', 0); insert into report_users values(null, 2, 1);
然后另一个报告只能由group_id = 1访问
insert into reports values(null, 'report 3 only for group_id 1', 0); insert into report_groups values(null, 3, 1);
现在,我有 3 行:每一行都可以访问,一行只能由 user_id = 1 访问,另一行只能由 group_id = 1 访问。
给我 user_id = 1 的所有行:
select reports.* from reports, report_users,report_groups where reports.public_access = 1 or (report_users.report_id = reports.id and report_users.user_id = 1) or (report_groups.report_id = reports.id and report_groups.group_id = 5) ;
我得到 2 行。它有效。
给我 group_id = 1 的所有行:
select reports.* from reports, report_users,report_groups where reports.public_access = 1 or (report_users.report_id = reports.id and report_users.user_id = 4) or (report_groups.report_id = reports.id and report_groups.group_id = 1) ;
我得到 2 行。它有效。
但是。如果report_users或report_groups为空,我不会得到任何结果。我首先运行此查询:
truncate table report_groups;
当我运行与以前相同的查询时,我得到一个空集。为什么?实际上,看起来我发送的 user_id 和 group_id 没有任何区别。我总是会得到 0 行。
对我来说,似乎只是因为两个表之一是空的,所以我没有得到任何结果。 查询本身有问题吗?
P粉0879514422023-09-14 12:48:37
你用这行代码做什么:
from reports, report_users,report_groups
是 3 个表的(旧式)CROSS JOIN
,这意味着如果其中一个表为空,则结果也为空。
而是使用EXISTS
:
select r.* from reports r where r.public_access = 1 or exists (select * from report_users u where u.report_id = r.id and u.user_id = ?) or exists (select * from report_groups g where g.report_id = r.id and g.group_id = ?);