5
id 标题 slug 摘要
------------------------------
1 标题1 slug1 摘要1
2 标题2 slug2 摘要2
3 标题3 slug3 摘要3
4 标题4 slug4 摘要4

我正在尝试选择所有字段,同时选择上/下一行的 id、title 和 slug

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);

该查询有效,但显然这不是明智的做法。

有人可以帮忙简化一下吗?谢谢

4

5 回答 5

2

好的,我认为这很容易。但是在没有一个可行的解决方案的一个小时之后,我将用我刚刚想出的方式回答我自己的问题。

使用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
标题 => 标题2
蛞蝓=>蛞蝓2
摘要 => 摘要2
prev_data => 1,title1,slug1
next_data => 3,title3,slug3

然后我必须explode(PHP)prev_datanext_data获取详细信息。

我仍在寻找一种(更好的)方法来仅使用 MySQL 来做到这一点。

于 2012-11-16T11:37:43.653 回答
1

假设Idauto_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);

否则,您发布的答案是正确的。

于 2012-11-16T11:43:35.373 回答
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但是,如果您必须在 where 中使用子句,这将不起作用;您需要为id...的每个值运行此查询

于 2012-11-16T10:17:27.670 回答
0

很抱歉解决了一个 6 岁问题,但必须这样做 :)
LAG()LEAD()进行救援!
非常方便,在 Oracle 和 SQL Server 中也可用:

select 
    title, lead (title) over (order by id) next_title, lag (title) over (order by id) prev_title,
    slug, lead (slug) over (order by id) next_slug, lag (slug) over (order by id) prev_slug,
    summary, lead (summary) over (order by id) next_summary, lag (summary) over (order by id) prev_summary,
    id, lead (id) over (order by id) next_id, lag (id) over (order by id) prev_id
from `table`
;
/*
create table `table` as
(select id, concat('title', id) title, concat('slug', id) slug, concat('summary', id) summary
from
(select 1 id union all
select 14 id union all
select 34 id union all
select 13 id union all
select 2 id union all
select 4 id ) as q)
*/
于 2019-09-17T09:56:44.600 回答
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)
于 2016-08-11T13:52:55.267 回答