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:
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:
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
.
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
The reason you don't get the results you want is the WHERE clause.
Put the conditions in the ON clause:
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. By placing the condition in the ON clause of the join it is still there although there is no match in the other table.
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.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.