2015-01-04 14 views
-2

[增訂]在一個查詢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)) 
+1

你的問題不清楚..請解釋清楚 – sumit

+0

我希望這將有助於說清楚 –

+0

所以你沒有LIMIT子句在任何地方? – Strawberry

回答

1

MySQL documentation明確規定:由單個SELECT語句的使用順序的暗示一無所知的順序的行出現在最終結果中,因爲默認情況下,UNION會生成無序的一組行。

我建議你用一個簡單的查詢:

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中。

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億票)。

+0

好吧,我不一定需要最新/最舊的訂單。這只是一個例子... –

+0

@MustafaMJalal:那麼你究竟需要什麼?如果你不解釋你的實際問題,我們如何回答你的問題? – siride

+0

正如文檔中所解釋的那樣,'UNION'不保留它所結合的'SELECT'所產生的行的順序,並且不能保證第一個'SELECT'產生的行先於第二個' SELECT'。與'LIMIT'結合使用'SELECT'查詢時使用'ORDER BY'非常有用。爲了在'UNION'結果集上實現排序,你必須將'SELECT'放入括號中,並在'UNION'級別添加一個ORDER BY'子句。爲了保持行的順序,你可以「SELECT」一個額外的計算列,其中包含一個正確製作的表達式。 – axiac

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代碼中的第一列,然後將其放入正確的數組中以獲取所需的嵌套數組。

編輯:添加到派生表的別名。不要太挑剔,但是在你寫下「不工作」的同時,你可能會發現這個遺漏並且有一個工作查詢。來吧隊友,答案在這裏幫助,並不總是爲你做你的工作:)

+0

甚至不工作 –

+0

@MustafaMJalal:是的。給定的查詢沒有任何問題。 – siride

+0

它說 每個派生表必須有它自己的別名 –

0

我知道這將是一個理想的答案,但至少我沒有必要mysql查詢兩次。 ,因爲我知道每個選區只需要兩條記錄。

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

現在這甚至使得它更容易使用時檢索到的HTML工作...