简体   繁体   English

MySQL的左联接不像左联接

[英]mysql LEFT JOIN not acting like left join

Here's my problem. 这是我的问题。 I have to get a list of questions and their answers in the same query. 我必须在同一查询中获得问题及其答案的列表。 If the answer is older than 30 days, I want to get an empty reply, but I still want the question: 如果答案早于30天,我想得到一个空的答复,但我仍然想要这个问题:

Im trying to do a left join, but if there is no match the question is still not showing up. 我试图做一个左联接,但是如果没有匹配,问题仍然没有出现。 You can see the schema and my select in this sqlfiddle and also down here: 您可以在此sqlfiddle中以及下面查看此模式和我的选择:

http://sqlfiddle.com/#!9/a88184/1 http://sqlfiddle.com/#!9/a88184/1

SELECT p.*
     , r.nota
     , r.replied 
  FROM preguntas p 
  LEFT 
  JOIN respuestas r 
    ON p.id = r.id_pregunta 
   AND r.uuid_user ="f6912e4bb23130b9" 
 WHERE r.replied > DATE_SUB(NOW(),INTERVAL 30 DAY) 
   AND p.id_formulario = "1" 
   AND activo ="1" 
 ORDER 
    BY orden ASC

Schema 架构图

CREATE TABLE `preguntas` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`id_formulario` INT(11) NOT NULL,
`pregunta` TEXT NULL COLLATE 'utf8_spanish_ci',
`opcional` TINYINT(1) NOT NULL DEFAULT '0',
`activo` TINYINT(1) NOT NULL DEFAULT '0',
`orden` INT(11) NOT NULL,
PRIMARY KEY (`id`))

COLLATE='utf8_spanish_ci'
ENGINE=InnoDB
ROW_FORMAT=DYNAMIC
AUTO_INCREMENT=302
;

CREATE TABLE `respuestas` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`intento` INT(11) NOT NULL DEFAULT '1',
`id_formulario` INT(11) NOT NULL,
`id_pregunta` INT(11) NULL DEFAULT NULL,
`uuid_user` VARCHAR(50) NULL DEFAULT NULL COLLATE 'utf8_spanish_ci',
`nota` INT(11) NULL DEFAULT NULL,
`replied` TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`))

COLLATE='utf8_spanish_ci'
ENGINE=InnoDB
ROW_FORMAT=DYNAMIC
AUTO_INCREMENT=1259;

INSERT INTO `preguntas` (`id`, `id_formulario`, `pregunta`, `opcional`, `activo`, `orden`) VALUES (126, 1, 'INICIATIVA PERSONAL', 0, 1, 1);
INSERT INTO `preguntas` (`id`, `id_formulario`, `pregunta`, `opcional`, `activo`, `orden`) VALUES (139, 1, 'TENER RAPIDEZ Y AGILIDAD', 0, 1, 5);

INSERT INTO `respuestas` (`id`, `intento`, `id_formulario`, `id_pregunta`, `uuid_user`, `nota`, `replied`) VALUES (174, 1, 1, 126, 'f6912e4bb23130b9', 4, '2019-05-23 18:08:15');
INSERT INTO `respuestas` (`id`, `intento`, `id_formulario`, `id_pregunta`, `uuid_user`, `nota`, `replied`) VALUES (175, 1, 1, 139, 'f6912e4bb23130b9', 4, '2019-04-03 18:08:15');

Current result: 当前结果:

id  id_formulario   pregunta    opcional    activo  orden   nota    replied
126 1   INICIATIVA PERSONAL false   true    1   4   2019-05-23T18:08:15Z

Expected result: 预期结果:

id  id_formulario   pregunta    opcional    activo  orden   nota    replied
126 1   INICIATIVA PERSONAL false   true    1   4   2019-05-23T18:08:15Z
139 1   TENER RAPIDEZ Y AGILIDAD    false   true    5   (empty) (empty)

Putting the left table's columns in where clause effectively turns the left join into an inner join . 将左表的列放在where子句中可以有效地将left join变为inner join

To prevent that, Move the condition to join: 为防止这种情况,请移动条件以加入:

SELECT p.*, r.nota, r.replied FROM preguntas p 
LEFT JOIN respuestas r ON p.id = r.id_pregunta 
    AND r.uuid_user ="f6912e4bb23130b9" and r.replied > DATE_SUB(NOW(),INTERVAL 30 DAY) 
where p.id_formulario = "1" AND activo ="1" ORDER BY orden ASC

sqlfiddle sqlfiddle

The reason you don't get the results you want is the WHERE clause. 无法获得所需结果的原因是WHERE子句。
Put the conditions in the ON clause: 将条件放在ON子句中:

SELECT p.*, r.nota, r.replied FROM preguntas p 
LEFT JOIN respuestas r 
ON p.id = r.id_pregunta AND r.uuid_user ="f6912e4bb23130b9" 
AND r.replied > DATE_SUB(NOW(),INTERVAL 30 DAY) 
AND p.id_formulario = "1" AND activo ="1" 
ORDER BY orden ASC

This condition: 这种情况:

r.replied > DATE_SUB(NOW(),INTERVAL 30 DAY)

removes the row from the results when it is placed in the WHERE clause, this is why you don't see it. 当将行放在WHERE子句中时,将从结果中删除该行,这就是为什么看不到它的原因。 By placing the condition in the ON clause of the join it is still there although there is no match in the other table. 通过将条件放在联接的ON子句中,尽管其他表中没有匹配项,但条件仍然存在。
For the other 2 conditions: 对于其他两个条件:

p.id_formulario = "1" AND activo ="1"

I'm not sure if you want them to reduce the results, so keep them in WHERE. 我不确定您是否希望它们减少结果,因此请将它们放在WHERE中。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM