(如何)我可以在单个查询中按行/结果顺序对查询结果组进行编号?

时间:2012-08-24 11:59:18

标签: mysql sql select

我的查询当前返回的数据具有以下属性:

  • 数字 A ,保证在结果中是唯一的(不在源表中);结果按A排序,但结果中A的值不一定是连续的。
  • 为多行重复的 B 键,将它们标记为同一组的一部分。它来自与A相同的表格。

示例:

+--+-+-+
|id|A|B|
+--+-+-+
| 5|1|2|
|15|3|2|
|12|4|5|
|66|6|5|
| 2|7|2|
+--+-+-+

我在这里看到的答案解释了如何在结果中返回行号。然而,我需要的是获得(优选的基于1的)订单号,同时保持每个 B 的不同计数。在下表中, C 是所需的结果:

+--+-+-+-+
|id|A|B|C|
+--+-+-+-+
| 5|1|2|1|
|15|3|2|2|
|12|4|5|1|
|66|6|5|2|
| 2|7|2|3|
+--+-+-+-+

这有点超出了我目前的SQL技能,所以我会感谢任何指针。包括指向现有答案的指针!

编辑:以下两个答案在结果方面同样有效(使用虚拟包装查询进行排序)。谢谢大家的帮助。哪个是最有效的查询?考虑到在我的特定用例中,从原始查询返回的行数永远不会很大(假设最多50行,甚至这是想象力的一部分)。此外,原始查询具有用于从其他关系获取数据的连接,尽管它们与排序或过滤无关。最后,所有结果都可能具有相同的 B ,或者每个结果都具有不同的 B - 它可以在两者之间或之间的任何位置。< / p>

3 个答案:

答案 0 :(得分:6)

你基本上想要的是RANK()功能。但是,由于它在MySQL中不可用,您可以使用以下方法进行模拟:

SELECT *
FROM (
  SELECT a, b, (CASE b 
                WHEN @partition THEN @rank := @rank + 1 
                ELSE @rank := 1 AND @partition := b END) AS c
  FROM tbl, (SELECT @rank := 0, @partition := '') tmp
  ORDER BY b, a
) tmp
ORDER BY a

DEMO (SQL小提琴)。

答案 1 :(得分:4)

select p.*, @i := if(@lastB != p.B, 1, @i + 1)
,@lastB := p.B as B
from table_name p, 
(select @i := 0) vt1,
(select @lastB := null) vt2
order by B;

试试这段代码。 (未经测试)

修改 使用sqlfiddle进行演示http://sqlfiddle.com/#!2/412df/13/2

答案 2 :(得分:0)

这不会非常有效,因为您的查询必须计算两次,然后再计算一组:

SELECT 
    q.* ,
    COUNT(*) AS c              --- the "Rank"
FROM 
    yourQuery AS q
  JOIN
    yourQuery AS qq
      ON  qq.B = q.B
      AND qq.A <= q.A
GROUP BY
    q.A ;