我有三张桌子:

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));

我要从至少满足以下条件之一的Reports-TABLE中获取行:

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)
;   

我有两排.它起作用了.

给我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)
;       

我有两排.它起作用了.

但.如果REPORT_USERS或REPORT_GROUPS为空,则不会得到任何结果.我首先运行以下查询:

truncate table report_groups;

当我像以前一样运行相同的查询时,我得到一个空集.为什么?实际上,我发送的USER_ID和GROUP_ID似乎没有任何区别.我将始终得到0行.

在我看来,只是因为两张桌子中的一张是空的,我就得不到任何结果. 是查询本身有问题吗?

推荐答案

您对此行执行的操作:

from reports, report_users,report_groups

is a (old style) CROSS JOIN of the 3 tables, which means that if one of the tables is empty then the result is also empty.

改为使用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 = ?);

Mysql相关问答推荐

正在获取MySQL死锁,因为这个查询需要很长时间.

无法从容器从APS. NET应用程序连接到MySQL服务器容器

MySQL:返回所有条件(但不满足其他条件)为真的所有结果

无法从mysql数据库获取数据

如何获取每日登录用户数?

MySQL,递归 CTE.它如何以这种句法形式工作?

MySQL Procedure 变量在 count(*) 上接收 null

我在 mysql 查询中需要帮助,我想在年龄之间按年龄过滤器分组,并显示 0 计数之间找不到的数据

当每组的列值发生变化时 Select 并连接行

为什么这个 NOT NULL 到 NULL 迁移会触发大量 I/O 操作?

MySQL - 考虑到所有前几天,每天计算唯一用户

MySQL按连续值和计数分组

试图获取非对象的属性

函数 mysql_real_escape_string 的 PDO 类似功能是什么?

我如何决定何时使用右连接/左连接或内连接或者如何确定哪个表在哪一侧?

PDO:MySQL 服务器已消失

在 PHP/MySQL 中将日期时间存储为 UTC

在 MySQL 中存储 IPv6 地址

在 MySQL Workbench 中导出超过 1000 条记录的查询结果

如果另一列为空,则 Select 一列