【问题标题】:mySQL innerjoin with where condition does not work带有 where 条件的 mySQL 内部联接不起作用
【发布时间】:2015-06-28 13:33:47
【问题描述】:

我正在尝试获取过去几个小时的 mysql 查询结果,但没有得到。我希望你能帮助我。

我有两张桌子。第一个表称为“驱动器”,非常大,有超过 200000 行和 30 列,结构如下:

 plate | time from        | time to
 ab222 | 2015.05.12 08:00 | 2015.05.13 11:37
 cv481 | 2015.05.14 12:08 | 2015.05.14 14:11 

第二个称为“燃料”,长度要短得多,大约 5000 行,但也有 22 列。它的结构是这样的:

 plate | time             | amount | price
 ab222 | 2015.05.13 09:22 | 2.3    | 32.22
 cv481 | 2015.05.14 13:59 | 12.2   | 17.7

我要做的是为“燃料”表中的每一行显示正确的“驱动器”。这意味着“燃料”表的时间必须介于“驱动器”表的“开始时间”和“结束时间”之间,并且盘子必须相同。结果应该显示两个表的列(大约 52 列和 5000 行,因为对于“燃料”表中的每一行,必须是“驱动器”表中的一个合适的驱动器)。

我不习惯使用 mysql,所以我搜索了很多并尝试了很多。我所做的以下尝试似乎接近我所需要的:

INNER JOIN fuel.* ON
drives.plate = fuel.plate
WHERE fuel.time Between
drives.timefrom AND
drives.timeto

但是没有用。

*****更新*****

感谢您迄今为止的帮助。我玩了一些查询,并注意到一个非常奇怪的行为。但首先你们是对的——我决定不使用“JOIN”,而是查询 2 个表并显示组合结果。这似乎是更好的解决方案。

但是现在的问题。当我在 phpMyAdmin 中查询时,结果是正确的,并且显示了一些匹配项。但是当我将相同的查询传输到 php 时,它会显示错误。

这是我连接到我的数据库的方法。效果很好:

$con = mysqli_connect("localhost","root","pass","test"); 
mysqli_options($init, MYSQLI_OPT_LOCAL_INFILE, true);    

下面是 phpMyAdmin 中的 MySQL 查询:

SELECT fuel.* , drives.* FROM fuel, drives WHERE fuel.plate = drives.PLATE 
AND fuel.time BETWEEN drives.time from AND drives.time to

这里在php中也是一样的:

$con ­> query ("SELECT fuel.* , drives.* FROM fuel, drives WHERE fuel
plate = drives.PLATE AND fuel.time BETWEEN drives.time from AND 
drives.time to");

并且它在第一行的以下代码块中导致错误“警告:mysql_fetch_array() 期望参数 1 是资源,布尔值给定错误”:

<?php while($row=mysql_fetch_array($con))  {   ?>      <tr>      <td><p>
<?php echo $row['product_id']; ?></p></td>      <td><p>
<?php echo $row['product_name']; ?></p></td>      <td><p>
<?php echo $row['cat_name']; ?></p></td>      </tr>   <?php  } ?>   

我搜索了很多,并找到了一些答案,例如变量 $con 为“空”或数组错误。但是,如果我使用以下查询来导入 csv 文件,它正在工作:

$con­>query( "LOAD DATA LOCAL INFILE 'drives.csv' INTO TABLE 
rentals FIELDS TERMINATED BY '' ENCLOSED BY '\"' LINES 
TERMINATED BY '\r\n' IGNORE 1 LINES");

很遗憾,我无法让我的查询和结果显示正常工作。很抱歉打扰你,但你能告诉我,有什么问题吗?非常感谢。

***** 工作解决方案 *****

我让它工作了。我的查询是错误的。这是工作的:

$blub = mysqli_query($con,"SELECT fuel.* , drives.* FROM fuel, drives 
WHERE fuel.plate = drives.PLATE AND fuel.time BETWEEN drives.time_from AND 
drives.time_to");

【问题讨论】:

  • 不工作是什么意思?是错误还是什么?
  • 我相信它的INNER JOIN fuel ON.... 不需要*
  • 请提供一个完整示例,说明您希望一行的外观
  • @Rahul:它什么也没发生。马丁:结果应该是盘子|时间从|时间到|盘子| 高分辨率照片| CLIPARTO时间 |金额 |符合条件时的价格

标签: php mysql database join


【解决方案1】:

您发布的 SQL 部分最明显的错误之一是在表名之后包含 .*

在 MySQL 中,INNER 关键字的添加/省略对语句没有任何影响,即a INNER JOIN ba JOIN b 同义。

谓词可以出现在ON 子句或WHERE 子句中。鉴于谓词是两个表中列的比较,将它们分开有点奇怪,ON 子句中的一个条件和WHERE 子句中的另一个条件。数据库不关心这些条件是在ON 子句还是WHERE 子句中。但由于这两个条件似乎都是关于“匹配”行,所以(对我来说)这两个条件都在 ON 子句中是有道理的。

举个例子:

 SELECT drives.plate
      , drives.timefrom
      , drives.timeto
      , fuel.plate
      , fuel.time
      , fuel.amount
      , fuel.price
   FROM drives 
   JOIN fuel
     ON fuel.plate = drives.plate
    AND fuel.time BETWEEN drives.timefrom AND drives.timeto

跟进

问:查询导致错误

 SELECT fuel.* , drives.* FROM fuel, drives WHERE fuel.plate = drives.PLATE 
 AND fuel.time BETWEEN drives.time from AND drives.time to

答:你有虚假的空格,应该有一个没有空格的列名

              BETWEEN drives.time from AND drives.time to
                                 ^                    ^

如果列名中有空格,则需要通过将其括在反引号中来“转义”列名:

              BETWEEN drives.`time from` AND drives.`time to` 
                             ^         ^            ^       ^ 

跟进

也许我之前的例子不够清楚。

用 JOIN 关键字替换过时的逗号语法

已经是 2015 年了。 抛弃连接操作的老式逗号语法已经过去了,并用更新的JOIN关键字替换它。 (将JOIN 关键字称为“较新”真的仍然有效吗?)

将连接谓词从 WHERE 子句移至 ON 子句

数据库并不关心;它与内部连接没有区别,谓词是谓词是谓词。但我们通常将指定如何“匹配”行的谓词放在ON 子句中,并将过滤结果集的谓词放在WHERE 子句中。

我们这样做的原因是为了让未来的读者更容易破译和理解语句在做什么。

还有

不要在SELECT列表中使用.*,具体标识你需要返回的表达式

table_name.* 是方便的简写。但最好列出您需要返回的列和表达式。我们经常发现.* 查询返回的列比实际需要的多。

虽然您的 ***** WORKING SOLUTION ***** 中的查询可能有效,但它确实不太理想。

  • fueldrives 之间的逗号替换为关键字JOIN
  • 将关键字WHERE 替换为ON
  • 仅指定您需要在 SELECT 列表中返回的列

【讨论】:

  • 你有一个虚假的空间应该是一个列名timefrom...这里BETWEEN drives.time from
  • 哦,是的,你是对的。我修好了它。但是while循环中的错误“警告:mysql_fetch_array()期望参数1是资源,布尔给定错误”仍然是相同的
  • 关于该错误的问题被多次询问和回答。进行搜索。 mysql_ 接口已弃用。请改用mysqliPDO。检查查询执行的返回。如果查询成功,则返回结果集,如果查询不成功,则返回 FALSE(布尔值)。在您尝试将其作为参数传递给 fetch 之前,请检查这一点。 (如果你的代码没有检查返回,它实际上是把它的小指放在嘴角,邪恶博士的风格,并说“我只是假设一切都会按计划进行,什么?”)
  • 您正在混合 mysqli 和 mysql 接口调用。不要那样做,这是行不通的。仅使用 mysqli。它看起来(从您发布的几段代码中)您正在混合过程风格和看起来像面向对象风格的函数调用。我强烈建议您坚持使用其中一种。你已经完成了程序风格mysqli_connect,所以也做了程序风格mysqli_query...$rs = mysqli_query($con,$sql); if (!$rs) { ... } else { echo "error"; }
【解决方案2】:

您的查询应该是

SELECT fuel.* FROM fuel 
INNER JOIN drives 
ON
drives.plate = fuel.plate
WHERE fuel.time Between
drives.timefrom AND
drives.timeto

【讨论】:

    【解决方案3】:

    改变

    INNER JOIN fuel.* ON
    

    INNER JOIN fuel  ON
    drives.plate = fuel.plate
    WHERE fuel.time Between
    drives.timefrom AND
    drives.timeto
    

    【讨论】:

      猜你喜欢
      • 2011-07-13
      • 2017-06-20
      • 2017-06-27
      • 1970-01-01
      • 2018-10-17
      • 2012-09-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多