Maison  >  Questions et réponses  >  le corps du texte

La requête dans MySQL donne 0 résultat si l'une des tables est vide

J'ai ces 3 tables :

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

Je souhaite obtenir les lignes du tableau de rapport qui satisfont au moins une des conditions suivantes :

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

Tout d'abord, je crée un nouveau rapport accessible publiquement :

insert into reports values(null, 'report 1 open to all', 1);

Ensuite, un autre rapport n'est accessible que par user_id = 1 :

insert into reports values(null, 'report 2 only for user_id 1', 0);
insert into report_users values(null, 2, 1);

Ensuite, l'autre rapport n'est accessible que par group_id=1

insert into reports values(null, 'report 3 only for group_id 1', 0);
insert into report_groups values(null, 3, 1);

Maintenant, j'ai 3 lignes : chacune est accessible, une ligne n'est accessible que par user_id = 1 et une autre ligne n'est accessible que par group_id = 1.

Donnez-moi toutes les lignes où 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)
;

J'ai 2 lignes. Ça marche.

Donnez-moi toutes les lignes avec 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)
;

J'ai 2 lignes. Ça marche.

Mais. Si report_users ou report_groups sont vides, je n'obtiens aucun résultat. Je lance d'abord cette requête :

truncate table report_groups;

Lorsque j'exécute la même requête que précédemment, j'obtiens un ensemble vide. Pourquoi? En fait, il ne semble pas y avoir de différence entre le user_id et le group_id que j'envoie. Je reçois toujours 0 lignes.

Pour moi, il me semble que c'est parce que l'une des deux tables est vide que je n'obtiens aucun résultat. Y a-t-il un problème avec la requête elle-même ?

P粉848442185P粉848442185403 Il y a quelques jours425

répondre à tous(1)je répondrai

  • P粉087951442

    P粉0879514422023-09-14 12:48:37

    Que faites-vous avec cette ligne de code :

    from reports, report_users,report_groups

    est le (ancien style) CROSS JOIN pour 3 tables, ce qui signifie que si l'une des tables est vide, le résultat est également vide.

    Utilisez plutôt 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 = ?);

    répondre
    0
  • Annulerrépondre