在select语句中使用join避免select

moiiocjp  于 2021-06-24  发布在  Mysql
关注(0)|答案(2)|浏览(453)

假设我有一个如下结构的数据库表
表记录:

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中的select在可伸缩性方面的问题。你知道怎么干净利落地做吗?可以使用连接吗?

jecbmhm3

jecbmhm31#

假设你对每个父母都有唯一的优先权,我相信这是可行的:

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。
现场演示-sql fiddle
mzaanser

mzaanser2#

这将在这里为您工作,并避免使用您提到的子查询。你可以用电脑做你想做的事 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

相关问题