多个连接的SQL查询

时间:2016-06-14 18:39:21

标签: mysql sql

我在处理连接时遇到问题

这是我的第一张表:

CREATE TABLE IF NOT EXISTS `form` (
  `id_form` int(20) NOT NULL AUTO_INCREMENT,
  `nameform` varchar(50) NOT NULL,
  PRIMARY KEY (`id_form`)
)      

表格中的数据

INSERT INTO `form` (`id_form`, `nameform`) VALUES
  (1, 'Formulaire commun'),
  (2, 'Formulaire FCPR'),
  (3, 'Formulaire fonds d''amorçage'),
  (4, 'Formulaire FOPRODI'),
  (5, 'Formulaire ITP'),
  (6, 'Formulaire PASRI'),
  (7, 'Formulaire PCAM'),
  (8, 'Formulaire PIRD'),
  (9, 'Formulaire PMN'),
  (10, 'Formulaire PNRI'),
  (11, 'Formulaire PRF'),
  (12, 'Formulaire RIICTIC'),
  (13, 'Formulaire VRR');

我的第二张表userdata:

CREATE TABLE IF NOT EXISTS `donnée_utilisateur` (
  `id_d` int(20) NOT NULL AUTO_INCREMENT,
  `id_form` int(20) NOT NULL,
  `id_us` int(20) NOT NULL,
  PRIMARY KEY (`id_d`),
  KEY `id-form` (`id_form`),
  KEY `id-us` (`id_us`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=407 ;

ALTER TABLE `donnée_utilisateur`
ADD CONSTRAINT `fvdsvsd` FOREIGN KEY (`id_us`) REFERENCES `utilisateur` (`id_us`),
ADD CONSTRAINT `ssssssssssss` FOREIGN KEY (`id_form`) REFERENCES `form` (`id_form`);

其中的数据:

INSERT INTO `donnée_utilisateur` (`id_d`,  `id_form`, `id_us`) VALUES
  (380, 2, 6),
  (381,  2, 6),
  (382,  3, 6),
  (383,  3, 6),
  (384,  4, 6),
  (385,  5, 6);

最后是用户表:

CREATE TABLE IF NOT EXISTS `utilisateur` (
  `id_us` int(20) NOT NULL AUTO_INCREMENT,
  PRIMARY KEY (`id_us`),

) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=8 ;

数据:

INSERT INTO `utilisateur` (`id_us`) VALUES
  (3),
  (6),
  (7);

我想要做的是获取特定用户id_form表中不存在的userdata

我试过这样做:

SELECT f.id_form
FROM  `donnée_utilisateur` d
RIGHT JOIN `form` f ON f.id_form=d.id_form Where d.id_d IS NULL  

如果我们有这样的数据,则此查询会导致此结果:

id_form
1
6
7 
8
9
10
11
12
13

这是预期的结果,这是正确的。如果我想为特定用户提供此结果,我会改变它:

SELECT f.id_form
FROM  `donnée_utilisateur` d
RIGHT JOIN `form` f ON f.id_form=d.id_form 
INNER JOIN  `utilisateur` u ON u.id_us=d.id_us Where d.id_d IS NULL AND id_us=6

我什么也没得到,或者应该像我刚写的结果一样。 我们再举一个id_us=7

的例子
SELECT f.id_form
FROM  `donnée_utilisateur` d
RIGHT JOIN `form` f ON f.id_form=d.id_form 
INNER JOIN  `utilisateur` u ON u.id_us=d.id_us Where d.id_d IS NULL AND u. id_us=7

这会导致所有id_form从1到12,因为用户没有插入任何数据。

3 个答案:

答案 0 :(得分:3)

右连接非常难以阅读,因此容易出错。通常,您必须从必须从中获取数据的表开始,然后从左外连接表中获取数据。

让我们看看你的问题:

  1. 您在表donnée_utilisateur之后加入,因此donnée_utilisateur将外部联接到其他表格。
  2. 其他表格为formutilisateur。您没有合并这两者的加入条件,因此您可以交叉加入它们,即将每个form与每个utilisateur合并。
  3. 所以,对于这个交叉加入产品,您可以加入外部donnée_utilisateur
  4. Where d.id_d IS NULL使其成为反连接。用于替换DBMS中仅具有这些直接方法存在弱点的NOT EXISTSNOT IN的技巧。您可以使用它来获取form中没有条目的所有utilisateur / donnée_utilisateur组合。可能很多。
  5. Where id_us=6进一步缩小了结果范围。不幸的是你忘了使用限定符。是u.id_us还是d.id_us? DBMS无法知道。让我们说它决定你的意思d.id_us。该字段始终为空,因为您只是驳回了所有匹配项。 d.id_us = 6永远不会成立,因此所有行都会被丢弃。你的结果是空的。如果DBMS认为您的意思是u.id_us,那么您可以获得结果,尤其是一遍又一遍id_form
  6. 您可能想要添加限定符u,但我建议您重新编写整个查询并使用NOT INNOT EXISTS

    还有utilisateur对你的查询做了什么?我认为你在donnée_utilisateur寻找不存在用户6的表单。为什么要加入utilisateur? (如果你加入它,你应该把它加入到donnée_utilisateur。)

答案 1 :(得分:2)

您可以使用子选择

select id_form  from form where 
id_form not in (select distinct id_form from  donnée_utilisateur where id_us=6 )

或正确的RDBMS引擎

select id_form  from form where 
id_form not in (select  id_form from  donnée_utilisateur where id_us=6 )

答案 2 :(得分:1)

Thorsten非常善于澄清,但未提供完整的查询来帮助您。您原来的右连接查询非常接近。但是,我已按如下方式切换到左连接:

SELECT
      f.id_form,
      f.nameform
   from
      form f
         left join donnée_utilisateur d
            ON f.id_form = d.id_form 
            AND d.id_us = 6
   where 
      d.id_d IS NULL

所以,我从FORM表开始获取ID和名称。没问题。现在,您考虑在辅助表中找不到表单,因此这是表单ID上的左连接并在where子句中查找NULL。但是,这本身就是为任何用户提供表格。要最终确定您对特定用户的需求,只需将AND子句添加到辅助表,以便THAT部分保留为FORM AND特定用户的左连接,从而导致d.id_d列为NULL

相关问题