查询没有给出正确的结果(PHP / MySQL)

时间:2013-06-16 23:45:44

标签: php mysql temp-tables

我从一个很长的查询得到了一个奇怪的结果,我将在这里简化:

DROP TEMPORARY TABLE IF EXISTS table1;
CREATE TEMPORARY TABLE table1 AS
(SELECT 
parent.id as parent_id,
times.a_time,
times.sequence,
FROM times
LEFT JOIN parent ON times.parent_id=parent.id
WHERE times.stop_id=10);

DROP TEMPORARY TABLE IF EXISTS table2;
CREATE TEMPORARY TABLE table2 AS
(SELECT 
parent.id as parent_id,
times.b_time,
times.sequence,
FROM times
LEFT JOIN parent ON times.parent_id=parent.id
WHERE times.stop_id=15 );

--here comes PDO->exec();

SELECT table1.*, table2.b_time
FROM table1
LEFT JOIN table2 ON table1.parent_id=table2.parent_id
WHERE table2.parent_id IS NOT NULL AND table1.sequence<table2.sequence
ORDER BY table1.a_time

我正在使用EMS MySQL Manager 2007测试查询,而在PHP中我正在使用PDO查询。

为了获得最终结果,(我知道PDO不支持立即运行此完整查询并返回结果集),我在创建临时表后运行PDO->exec()(请参阅查询),然后我在最后PDO->query()上运行SELECT

$db = new PDO("mysql:host=".DB_HOST.";dbname=".DB_NAME, DB_USER, DB_PASS);
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$db->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);

$tempTablesSQL='DROP TEMPORARY TABLE IF EXISTS...'; //create temporary tables
$db->exec($tempTablesSQL);

$sql='SELECT table1.*, table2.b_time ...'; //JOIN and SELECT the results
$results=array();
foreach($db->query($sql) as $row){
  $results[]=$row;
}

print_r($results);

在MySQL管理器中,我立即运行整个查询,对于那些特定的ID,我得到29行作为结果(这是正确的,因为记录是从先前解析的文件中插入的,并通过将结果与文件我知道他们很好。)

但是在PHP中,我只获得了25个结果,并且b_time的值完全错误。

所以,我的问题是:

  • 为什么我的结果会出错?

  • 是我调用此查询错误的方法(在PHP中)?

感谢任何帮助。

- 的修改 -

这不只是PDO,我尝试使用mysqli_multi_query,我得到了同样错误的结果。

我注意到的一件重要事情是:如果我使用常规表而不是临时表,结果就可以了。

1 个答案:

答案 0 :(得分:0)

让我尝试在你的问题的第二部分提出一些建议, 是我调用此查询错误的方法吗?

首先,您似乎不需要创建任何临时表。根据您展示的内容,整个事情可以是单个查询,如

SELECT q1.parent_id, q1.a_time, q1.sequence, q2.b_time
  FROM
(
    SELECT p.id parent_id, t.a_time, t.sequence
      FROM times t LEFT JOIN parent p
        ON t.parent_id=p.id
     WHERE t.stop_id = ?
 ) q1 LEFT JOIN
(
    SELECT p.id as parent_id, t.b_time, t.sequence
      FROM times t LEFT JOIN parent p
        ON t.parent_id=parent.id
     WHERE t.stop_id = ?
) q2 ON q2.parent_id IS NOT NULL 
    AND q1.sequence < q2.sequence
 ORDER BY q1.a_time

并将其作为预备声明执行

...
$sql = 'SELECT ...'; // the whole thing from above
$query = $db->prepare($sql);
$query->execute(array($stop_id1, $stop_id2));
$result = $query->fetchAll(PDO::FETCH_ASSOC);

var_dump($result);

现在即使出于某种原因你必须在返回结果集之前使用临时表并执行一些操作,然后我建议将它包装起来一个存储过程

DELIMITER $$
CREATE PROCEDURE sp_myproc (IN stop_id1 INT, IN stop_id2 INT, ...)
BEGIN
    DROP TEMPORARY TABLE IF EXISTS table1;
    CREATE TEMPORARY TABLE table1 AS
    ...
    WHERE times.stop_id = stop_id1;

    DROP TEMPORARY TABLE IF EXISTS table1;
    CREATE TEMPORARY TABLE table1 AS
    ...
    WHERE times.stop_id = stop_id2

    -- return the resultset
    SELECT table1.*, table2.b_time
    FROM table1
    ...
END$$
DELIMITER ;

从php

调用你的程序一次
...
$sql = 'CALL sp_myproc(?, ?)';
$query = $db->prepare($sql);
$query->execute(array($stop_id1, $stop_id2));
$result = $query->fetchAll(PDO::FETCH_ASSOC);

var_dump($result);

现在关于问题的第一部分 为什么我会得到错误的结果? OUTER加入可能很棘手,特别是当你链接它们时。您可以轻松地过滤掉一些行或生成其他行(最常见的情况)。

您删除的少数连接可能是原因。

无论如何,提供的信息还不足以得出结论性答案。

但是我会建议而不是返回列,因为table1.*显式指定所有列,并为在属于连接的不同表中具有相同名称的列提供显式别名。