说我有一个具有以下结构的数据库表
表记录:
id INT NOT NULL (PRIMARY_KEY, AUTO_INCREMENT)
parent INT NOT NULL
priority INT NUL NULL
现在,我想选择所有记录,但是我需要一个将每一行与具有相同的priority
的后续行(基于parent
,升序)相匹配的列-如果存在,否则为NULL
。在这个任意示例中,parent
是完全外部表的标识符,与记录直接无关。
例如数据集:
| id | parent | priority |
|----|--------|----------|
| 1 | 1 | 2 |
| 2 | 1 | 6 |
| 3 | 1 | 1 |
| 4 | 2 | 4 |
| 5 | 2 | 3 |
应产生以下内容:
| id | parent | priority | match |
|----|--------|----------|-------|
| 1 | 1 | 2 | 2 |
| 2 | 1 | 6 | NULL |
| 3 | 1 | 1 | 1 |
| 4 | 2 | 4 | NULL |
| 5 | 2 | 3 | 4 |
有效的SQL实现是:
SELECT r1.*,
(SELECT r2.id
FROM record AS r2
WHERE r2.parent = r1.parent
AND r2.priority > r1.priority
ORDER BY r2.priority ASC
LIMIT 1
) AS match_id
FROM record AS r1
但是,我非常关注SELECT-in-SELECT的可伸缩性。关于如何做到这一点的任何想法?可以使用JOIN吗?
答案 0 :(得分:1)
假设您对每个父母都有唯一的优先级,我相信这会起作用:
select r.id, r.parent, r.priority, r2.id as `match`
from (
select r.id, r.parent, r.priority, min(r2.priority) as next_priority
from record r
left join record r2 on
r.parent = r2.parent
and r.priority < r2.priority
group by r.id, r.parent, r.priority
) r
left join record r2 on
r.parent = r2.parent
and r.next_priority = r2.priority
order by r.id
match
是MySQL中的保留关键字,因此需要反引号。
此方法的工作原理是我们从高于当前顺序的升序中拉出下一个优先级,并基于此(并且我们对每个父级都有唯一的优先级)可以拉出相应的行ID。
答案 1 :(得分:0)
这将在这里为您工作,并且避免使用您提到的子查询。您可以通过LEFT
连接执行所需的操作,以便保留空值,然后将所需的内容放在on
上,例如r1.parent = r2.parent and r2.priority > r1.priority
http://sqlfiddle.com/#!9/3a592/25
SELECT r1.*, r2.id as 'Match'
FROM record r1
left join record r2 on r1.parent = r2.parent and r2.priority > r1.priority
group by r1.id