【问题标题】:SQL - query with INNER JOIN is not working propelySQL - 使用 INNER JOIN 的查询无法正常工作
【发布时间】:2018-12-07 00:21:00
【问题描述】:

我有表table_tudofollowItem,在表table_tudo 上我有1 列称为tipo,可以有三个值之一tipoEp, tipoOv and tipoFm,在这两个表上我想INNER JOIN dateMDitemName 列之后,我想在屏幕上仅打印与此条件匹配的项目 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();

【问题讨论】:

  • i tested this query 哪个查询?有很多
  • 这不是一个答案,但在加入表格时声明别名对缩短代码有很大帮助。
  • Natalie,请告诉我们这两个表的主键。或者您可以发送表格中的示例数据。这只是为了了解表的行为
  • 没有数据和参数值,这个问题是无法回答的。
  • @AnuraAdhikari 表 table_tudo 上的主键是 id,表 followItem 上的主键是 num,两者都带有 AUTO_INCREMENT。 “发送表格中的示例数据”我不知道是什么意思...

标签: mysql sql database join inner-join


【解决方案1】:

您要求日期等于且大于同时

您可能需要在 OR 条件中使用括号来控制它们的解释方式。

您依赖 MySQL 的非标准 group by 来过滤掉不需要的行,但这些只是近似值。

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

【讨论】:

  • 是的,我只是像您在代码中所做的那样添加了一个括号,它解决了我的问题,谢谢!
  • 我想只为:tipoEp 应用条件table_tudo.dateMD &gt; followItem.dateMD 这可能吗?
  • 是的,要做到这一点,您必须将所需的条件组合与括号“组合”在一起,例如( table_tudo.dateMD &gt; followItem.dateMD AND table_tudo.tipo = :tipoEp ) 但没有样本数据结束预期结果我真的不能提供更多
【解决方案2】:

您的主要查询大部分都在目标上。在这里,它被格式化为更容易阅读表格的相关性。我也为表名添加了别名以简化。 T 和 FI(别名)表之间的 JOIN 只是那些限定记录的那些......匹配 ID、用户和日期 GREATER。这是第 1 部分。

NEXT,是对“TIPO”限定词的限制。我将其更改为使用 IN 子句,因此如果 TIPO 是列表中的任何一个,则为 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

您可能遇到记录未正确返回的问题的原因是您在所有与没有任何括号的情况下都有 OR 条件。因此,只要它有匹配,它就会全线加入,可能是笛卡尔结果。

您的 GROUP by,您需要添加每个表中的列列表以帮助限制重复项以及您关心的列是哪个相应的表。

【讨论】:

    【解决方案3】:

    与目标描述相比,您的查询中有几个问题:

    • 您的联接中的 2 个条件需要 AND,而不是 OR。还有大部分WHERE条件可以直接移到JOIN,这样逻辑更容易理解

    • WHERE 子句中的运算符优先级问题;您需要将ORpart 括在括号中,否则它不会按照您的想法执行... AND (table_tudo.tipo= :tipoEp ORtable_tudo.tipo= :tipoFm ORtable_tudo.tipo@987654333子句,更容易阅读

    更新查询:

    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`
    

    PS:我怀疑GROUP BY 是否有用,尝试将其删除,看看会发生什么。

    【讨论】:

      【解决方案4】:

      试试这样的。

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-11-04
        • 1970-01-01
        • 1970-01-01
        • 2016-11-29
        • 2015-10-27
        • 1970-01-01
        • 2018-01-27
        • 1970-01-01
        相关资源
        最近更新 更多