2012-11-16 46 views
5
id title slug summary 
------------------------------ 
1  title1 slug1 summary1 
2  title2 slug2 summary2 
3  title3 slug3 summary3 
4  title4 slug4 summary4 

我想選擇所有字段,並在此同時,選擇ID,標題和上/下一個排的蛞蝓Simplifing MySQL的嵌套SELECT

SELECT 
    title, slug, summary, id as current_id, 
    (SELECT id FROM table WHERE id < current_id ORDER BY id DESC LIMIT 1) AS prev_id, 
    (SELECT title FROM table WHERE id < current_id ORDER BY id DESC LIMIT 1) AS prev_title, 
    (SELECT slug FROM table WHERE id < current_id ORDER BY id DESC LIMIT 1) AS prev_slug, 
    /* 
    (SELECT id ... ) AS next_id 
    (SELECT title...) AS next_title 
    ... 
    and if there are more fields to select, I have to repeat this (SELECT...) 
    */ 
FROM 
    table 
WHERE 
    id IN (2,3,4); 

查詢作品,但顯然它不是聰明的做法。

有些人可以幫助簡化這個嗎?由於

+0

在SQL中有一個更好的方法 - 只是沒有MySQL的有限SQL功能。 –

+1

我們非常渴望向您學習。 – 0xC0DEGURU

回答

0

你可以從一個子查詢中提取出列:

SELECT 
    title, slug, summary, id as current_id, prev.prev_id, prev.prev_title, prev.prev_slug, next.next_id, next.next_title, next.next_slug 
FROM 
    table, 
    (SELECT id AS prev_id, title AS prev_title, slug AS prev_slug FROM table WHERE id < 2 ORDER BY id DESC LIMIT 1) AS prev, 
    (SELECT id AS next_id, title AS next_title, slug AS next_slug FROM table WHERE id > 2 ORDER BY id DESC LIMIT 1) AS next 
WHERE 
    id = 2; 

但是,如果你在你在哪裏使用IN條款這是行不通的;你需要運行這個查詢爲每個值id ...

+0

太糟糕了我一次取多行......我以爲這很容易 – user1643156

1

好吧,我認爲這很容易。但是在一個小時沒有工作解決方案之後,我會用我剛剛發現的方式來回答我自己的問題。

使用CONCAT_WS

SELECT 
    title, slug, summary, id as current_id, 
    (
     SELECT 
      CONCAT_WS(',' id, title, slug) 
     FROM 
      table 
     WHERE 
      id < current_id ORDER BY id DESC LIMIT 1) 
    ) AS prev_data, 
    (
     SELECT 
      CONCAT_WS(',' id, title, slug) 
     FROM 
      table 
     WHERE 
      id > current_id ORDER BY id ASC LIMIT 1) 
    ) AS next_data 
FROM 
    table 
WHERE 
    id IN (2,3,4); 

,結果會是這樣的

 
id  => 2 
title  => title2 
slug  => slug2 
summary => summary2 
prev_data => 1,title1,slug1 
next_data => 3,title3,slug3 

然後我不得不explode(PHP)prev_datanext_data獲得詳細信息。

我仍然在尋找一種(更好的)方式來只用MySQL來做到這一點。

1

假設Id列是auto_increment和值不必id之間的間隙(這意味着它們在之間遞增爲1,2,3,4,無間隙樣1,3,4, 6),那麼你可以試試這個:

SELECT T.Id AS CurrentId 
    , T.Title AS CurrentTitle 
    , T.Slug AS CurrentSlug 
    , T.Summary AS CurrentSummary 
    , IFNULL(P.Id, -1) AS PreviousId 
    , IFNULL(P.Title, '') AS PreviousTitle 
    , IFNULL(P.Slug, '') AS PreviousSlug 
    , IFNULL(P.Summary, '') AS PreviousSummary 
    , IFNULL(N.Id, -1) AS NextId 
    , IFNULL(N.Title, '') AS NextTitle 
    , IFNULL(N.Slug, '') AS NextSlug 
    , IFNULL(N.Summary, '') AS NextSummary 
    FROM table T 
    LEFT JOIN table P ON P.Id - 1 = T.Id 
    LEFT JOIN table N ON N.Id + 1 = T.Id 
    WHERE T.Id IN (2, 3, 4); 

否則,你發佈的答案是正確的。

+1

謝謝凱爾。 id列_is_ auto_increment,但由於條目會不時刪除,所以無法保證無間隙。這就是爲什麼我必須使用>和<。 – user1643156

+0

我明白了。只是一個想法,如果您碰巧使用任何服務器端語言['C#','Java'等],也許您可​​以嘗試在代碼中獲取「前一個」和「下一個」記錄,而不是在查詢中。只是想平衡執行時間。 – KaeL

0

也許這樣的事情會起作用。我沒有測試它,所以我不確定,但看起來不錯:)

SELECT 
    current.title as current_title, 
    current.slug as current_slug, 
    current.summary as current_summary, 
    current.id as current_id, 
    prev.title as prev_title, 
    prev.slug as prev_slug, 
    prev.summary as prev_summary, 
    prev.id as prev_id, 
    next.title as next_title, 
    next.slug as next_slug, 
    next.summary as next_summary, 
    nexrt.id as next_id 
FROM 
    `table` current LEFT JOIN 
    `table` prev ON prev.id = current.id - 1 LEFT JOIN 
    `table` next ON next.id = current.id + 1      
WHERE 
    current.id IN (2,3,4)