2012-11-16 44 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)