【发布时间】:2010-12-04 23:43:18
【问题描述】:
我有一张这样的桌子:
等级信 1个 2个 3乙 4个 5℃ 6个 7℃ 8℃ 9乙 10℃我需要每个字母的前 2 个按升序排列:
等级信 1个 2个 3乙 5℃ 7℃ 9乙我该怎么做?使用 GROUP BY 获得前 1 名相当简单,但我似乎无法让它适用于多个条目
【问题讨论】:
我有一张这样的桌子:
等级信 1个 2个 3乙 4个 5℃ 6个 7℃ 8℃ 9乙 10℃我需要每个字母的前 2 个按升序排列:
等级信 1个 2个 3乙 5℃ 7℃ 9乙我该怎么做?使用 GROUP BY 获得前 1 名相当简单,但我似乎无法让它适用于多个条目
【问题讨论】:
SELECT mo.Letter, md.Rank
FROM (
SELECT DISTINCT letter
FROM mytable
) mo
JOIN mytable md
ON md.Letter >= mo.Letter
AND md.Letter <= mo.Letter
AND Rank <=
COALESCE
(
(
SELECT Rank
FROM mytable mi
WHERE mi.letter = mo.letter
ORDER BY
Rank
LIMIT 1, 1
),
0xFFFFFFFF
)
您需要在(Letter, Rank) 上有一个复合索引(按此顺序)
注意这个结构:
md.Letter >= mo.Letter
AND md.Letter <= mo.Letter
而不仅仅是md.Letter = mo.Letter
它强制Range checked for each record 更有效。
在我的博客中查看这篇文章:
了解更多详情。
【讨论】:
select distinct rank, letter
from table1 t2
where rank in
(select top 2 rank
from table1 t2
where t2.letter = t1.letter
order by rank)
order by letter, rank
编辑:(我的第一次尝试在 MySql 上不起作用(Quassnoi 评论),我修改它以在 sql server 上工作)
第二次尝试:
select t.letter, t.rank
from table1 t
join (
select t1.letter, min(t1.rank) m
from table1 t1
join (select t0.letter, min(t0.rank) m, count(1) c
from table1 t0 group by t0.letter) t2
on t1.letter = t2.letter and ((t2.c = 1) or (t2.c > 1 and t1.rank > m))
group by t1.letter) t3
on t.letter = t3.letter and t.rank <= t3.m
【讨论】: