SQL-使用INNER JOIN的查询无法正常工作

时间:2018-12-07 00:21:01

标签: mysql sql database inner-join

我有表table_tudofollowItem,在表table_tudo上,我有1列称为tipo,可以具有三个值tipoEp, tipoOv and tipoFm之一,在这两个表上,我想INNER JOINdateMDitemName之后,只想在屏幕上打印出符合条件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,因为它显示了重复的行。

我无法使用ANDINNER 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();

4 个答案:

答案 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' )