我有表table_tudo
和followItem
,在表table_tudo
上,我有1列称为tipo
,可以具有三个值tipoEp, tipoOv and tipoFm
之一,在这两个表上,我想INNER JOIN
列dateMD
和itemName
之后,只想在屏幕上打印出符合条件table_tudo.dateMD > followItem.dateMD AND followItem.user_id = :user_id AND table_tudo.tipo = :tipoEp OR table_tudo.tipo = :tipoFm OR table_tudo.tipo = :tipoOv
的项目。>
在查询结束时,我使用了GROUP BY
,因为它显示了重复的行。
我无法使用AND
来INNER JOIN
来自2个表的2列,然后我尝试使用OR
并成功了,但是现在我遇到了另一个问题,即条件table_tudo.dateMD > followItem.dateMD
不适用于table_tudo.tipo = :tipoFm OR table_tudo.tipo = :tipoOv
,这些tipo
的行全部打印在屏幕上,条件仅适用于table_tudo.tipo = :tipoEp
。
我的查询出了什么问题? PS:bindParam
中的变量是全局变量。
$MTEpPRP = $conn->prepare("SELECT * FROM `table_tudo` INNER JOIN `followItem` ON `table_tudo`.`itemName` = `followItem`.`itemName` OR `table_tudo`.`dateMD` = `followItem`.`dateMD` WHERE `table_tudo`.`dateMD` > `followItem`.`dateMD` AND `followItem`.`user_id` = :user_id AND `table_tudo`.`tipo` = :tipoEp OR `table_tudo`.`tipo` = :tipoFm OR `table_tudo`.`tipo` = :tipoOv GROUP BY `table_tudo`.`id`");
$MTEpPRP->bindParam(':tipoEp', $tipoEp, PDO::PARAM_STR);
$MTEpPRP->bindParam(':tipoFm', $tipoFm, PDO::PARAM_STR);
$MTEpPRP->bindParam(':tipoOv', $tipoOv, PDO::PARAM_STR);
$MTEpPRP->bindParam(':user_id', $user_id, PDO::PARAM_INT);
$MTEpPRP->execute();
我进行了一些测试,并且我还意识到,只有在查询table_tudo.tipo = :tipoFm OR table_tudo.tipo = :tipoOv
上有这一行时,table_tudo.tipo = :tipoEp
中的行才会打印在屏幕上。
我认为问题出在INNER JOIN
上,因为我在下面测试了这些查询并且有效:
$MTEpPRP = $conn->prepare("SELECT * FROM `table_tudo` WHERE `table_tudo`.`tipo` = :tipoOv");
$MTEpPRP->bindParam(':tipoOv', $tipoOv, PDO::PARAM_STR);
$MTEpPRP->execute();
$MTEpPRP = $conn->prepare("SELECT * FROM `table_tudo` WHERE `table_tudo`.`tipo` = :tipoFm");
$MTEpPRP->bindParam(':tipoFm', $tipoFm, PDO::PARAM_STR);
$MTEpPRP->execute();
$MTEpPRP = $conn->prepare("SELECT * FROM `table_tudo` WHERE `table_tudo`.`tipo` = :tipoFm OR `table_tudo`.`tipo` = :tipoOv");
$MTEpPRP->bindParam(':tipoFm', $tipoFm, PDO::PARAM_STR);
$MTEpPRP->bindParam(':tipoFm', $tipoOv, PDO::PARAM_STR);
$MTEpPRP->execute();
答案 0 :(得分:1)
您要要求日期等于并且大于同一时间
您可能需要使用带有OR条件的括号来控制它们的解释方式。
您依靠MySQL的非标准分组依据来过滤掉不需要的行,但这只是近似值。
SELECT *
FROM `table_tudo`
INNER JOIN `followItem` ON `table_tudo`.`itemName` = `followItem`.`itemName`
OR `table_tudo`.`dateMD` = `followItem`.`dateMD` << not making sense
WHERE `table_tudo`.`dateMD` > `followItem`.`dateMD` << not making sense
AND `followItem`.`user_id` = :user_id
AND ( << use parentheses
`table_tudo`.`tipo` = :tipoEp
OR `table_tudo`.`tipo` = :tipoFm
OR `table_tudo`.`tipo` = :tipoOv
) << use parentheses
GROUP BY `table_tudo`.`id` << select * with group by is MySQL nightmare
请参阅:https://dev.mysql.com/doc/refman/5.7/en/group-by-handling.html
答案 1 :(得分:1)
您的主要查询主要针对目标。在这里,它被格式化为使表格的关联更容易阅读。我还为表名添加了别名以简化。 T和FI(别名)表之间的JOIN只是那些符合记录条件的表...匹配ID,用户和日期为GREATER。这是第1部分。
下一步,是对“ TIPO”限定词的限制。我将其更改为使用IN子句,因此,如果TIPO是列表中的ANY,则为true。
SELECT
*
FROM
table_tudo T
INNER JOIN followItem FI
ON T.itemName = FI.itemName
AND FI.user_id = :user_id
AND T.dateMD > FI.dateMD
WHERE
T.tipo IN ( :tipoEp, :tipoFm, :tipoOv )
GROUP BY
T.id
您可能会遇到无法正确返回记录的问题的原因是,所有AND后面都带有或条件而没有任何括号。因此,一旦有一场比赛,它就全面加入,可能是笛卡尔的结果。
您的GROUP BY,您需要添加每个表中的列列表以帮助限制重复项以及列所关注的是哪个表。
答案 2 :(得分:1)
与目标描述相比,查询中存在几个问题:
您加入的两个条件需要一个AND
,而不是OR
。此外,大多数WHERE
条件都可以直接移至JOIN
,这使得逻辑更容易理解
在您的WHERE
子句中带有运算符优先级的问题;您需要将OR
部分放在括号中,否则将无法执行您认为的... AND (
table_tudo .
tipo = :tipoEp OR
table_tudo .
tipo {{1 }} table_tudo = :tipoFm OR
tipo .
IN`子句,它更易于阅读
更新的查询:
= :tipoOv). Better yet, use an
PS:我怀疑SELECT
*
FROM
`table_tudo`
INNER JOIN `followItem`
ON `table_tudo`.`itemName` = `followItem`.`itemName`
AND `table_tudo`.`dateMD` = `followItem`.`dateMD`
AND `table_tudo`.`dateMD` > `followItem`.`dateMD`
AND `followItem`.`user_id` = :user_id
WHERE
`table_tudo`.`tipo` IN (:tipoEp, :tipoFm, `table_tudo`.`tipo` = :tipoOv )
GROUP BY `table_tudo`.`id`
是否有用,请尝试将其删除并查看会发生什么情况。
答案 3 :(得分:1)
尝试这样的事情。
select * from table_tudo t
inner join followItem f on t.itemName = f.itemName
where f.dateMD > t.dateMD
and f.user_id = 'user_id' and (t.tipo ='tipoEp' or t.tipo ='tipoFm' or t.tipo
='tipoOV' )