id title slug summary ------------------------------ 1 title1 slug1 summary1 2 title2 slug2 summary2 3 title3 slug3 summary3 4 title4 slug4 summary4
我正在尝试选择所有字段,同时选择上一行/下一行的id,title和slu
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 :(得分: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_data
和next_data
来获取详细信息。
我仍然在寻找一种(更好)的方法来仅使用MySQL。
答案 1 :(得分:1)
假设 Id
列为auto_increment
且值在id
之间没有差距(意味着它们是增加为1,2,3,4。在1,3和4之间没有间隙,那么你可以试试这个:
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);
否则,您发布的答案是正确的。
答案 2 :(得分: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
...
答案 3 :(得分: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)
答案 4 :(得分: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)
*/