MySQL多个选择在一个查询中检索嵌套数组

时间:2015-01-04 06:32:05

标签: php mysql

[增订]

我正在尝试从一个表中选择数据,但尝试以不同的顺序获取它们

SELECT * FROM 
(
  SELECT * FROM videos ORDER BY timestamp DESC
) mostrecent

UNION ALL

SELECT * FROM
( 
  SELECT * FROM videos ORDER BY timestamp ASC
) oldest

现在这将以不同的顺序检索记录。最新的视频和最古老的视频......

foreach($table as $key=>$value)
{
$row_tmb[$key] = $value;
}
$array[] = $row_tmb;

打印数据时

print_r($array);

我得到了

Array ( [0] => Array ( [vid] => 1 [title] => title1 [timestamp] => newer) 
        [1] => Array ( [vid] => 2 [title] => title2 [timestamp] => older
        //from second select...
        [2] => Array ( [vid] => 2 [title] => title2 [timestamp] => older
        [3] => Array ( [vid] => 1 [title] => title1 [timestamp] => newer
)

我想要

Array('newest' => Array ( 
        [0] => Array ( [vid] => 1 [title] => title1 [timestamp] => newer) 
        [1] => Array ( [vid] => 2 [title] => title2 [timestamp] => older))
        //from second select...
Array('oldest' => Array (
        [0] => Array ( [vid] => 2 [title] => title2 [timestamp] => older
        [1] => Array ( [vid] => 1 [title] => title1 [timestamp] => newer))

3 个答案:

答案 0 :(得分:1)

您可以在select语句中使用外部查询,如下所示:

select
    *
from
    (
        SELECT
            'Newest',col1,col2,etc
        FROM
            (
            SELECT 
                * 
            FROM 
                videos 
            ORDER BY 
                timestamp DESC
            )mostrecent
        UNION ALL
        SELECT
            'Oldest',col1,col2,etc
        FROM
            (
            SELECT 
                * 
            FROM 
                videos 
            ORDER BY 
                timestamp DESC
            )oldest
    ) someTable
order by
    1 asc

然后,这将按照最新/最旧的顺序排序结果,然后按照您的顺序排序。

这不会给你两个数组,就像你展示你想要的输出一样,但除了在一个数组中,它几乎可以给你你想要的东西。但是,您可以简单地检查PHP代码中的第一列,然后将其放入正确的数组中以获取所需的嵌套数组。

编辑:为派生表添加了别名。不要挑剔,但在你写“甚至不工作”的同时,你可以找到遗漏并有一个有效的查询。来吧,伙伴,答案在这里帮助,而不是总是为你做你的工作:)

答案 1 :(得分:1)

MySQL documentation明确指出:对单个SELECT语句使用ORDER BY意味着行在最终结果中出现的顺序,因为UNION默认生成一组无序行。 / em>的

我建议您使用简单的查询:

SELECT *
FROM videos
ORDER BY timestamp DESC

获取PHP数组中的数据,然后使用PHP代码复制它并根据需要将其组合。这是一些使用mysqli的示例代码。使用PDO类似:

// You should add a LIMIT to the query or it will take a lot of time and consume
// a lot of memory when the table gets bigger (several thousand rows)
$query  = 'SELECT * FROM videos ORDER BY timestamp DESC';
$result = mysqli_query($connection, $query);

// Retrieve the data
$data = array();
while ($row = mysqli_fetch_assoc($result)) {
    $data[] = $row;
}

// Use the retrieved data to get the combined result
$array = array(
    'newest' => $data,
    'oldest' => array_reverse($data),
);

<强>更新

假设列timestamp包含一个整数值(时间戳),您可以使用如下查询从MySQL获得相同的结果:

(
    SELECT *, 'newest' AS source, timestamp AS sortColumn
    FROM videos
)
UNION ALL
(
    SELECT *, 'oldest' AS source, -timestamp AS sortColumn
    FROM videos
)
ORDER BY sortColumn DESC

如果timestamp列不是整数值而是DATE,请改用FROM_UNIXTIME(timestamp) AS sortColumn。我们的想法是计算一个可用于最终排序的值(UNION级别),并将其存储在新列sortColumn中。

PHP中使用source列来了解每条记录所属的组(最新记录与最旧记录)。

// The lists of data split by source
$array = array(
    'newest' => array(),
    'oldest' => array(),
);
// Retrieve the data, put it into the correct list
while ($row = mysqli_fetch_assoc($result)) {
    $array[$row['source']] = $row;
}

备注:对于中型和大型表(数千行甚至更多),它将运行缓慢,因为它无法使用索引。对于这种大小的表,无论如何选择所有记录都没有多大意义。你可能会写这样的东西:

(
    SELECT *, 'newest' AS source, timestamp AS sortColumn
    FROM videos
    ORDER BY timestamp DESC
    LIMIT 100
)
UNION ALL
(
    SELECT *, 'oldest' AS source, nbVotes AS sortColumn
    FROM videos
    ORDER BY timestamp ASC
    LIMIT 100
)
ORDER BY sortColumn DESC

选择最近的100行和最旧的100行。最终结果从最新的记录开始,按timestamp降序排序(最新的第一个),然后按照他们收到的投票数(列nbVotes)排序最早的记录,降序(我假设没有视频有更多超过13亿票。)

答案 2 :(得分:0)

我知道这将是一个理想的答案,但至少我没有两次mysql查询。 因为我知道每个选择只需要两条记录。

$newest = array($videos[0], $videos[1]);
$oldest = array($videos[2], $videos[3]);

现在这甚至使得在检索到HTML时更容易使用...