我有一个包含以下列的表:
身份证 | fk_id |接收日期

可能有多个记录具有共同的 fk_id,它代表相关表中的外键 id。

我需要创建一个查询,该查询将为每条记录分配一个行号,按 fk_id 分组,按 rcv_date 排序。

我最初从以下查询开始,它非常适合排序和分配行号:

SELECT @row:=@row +1 AS ordinality, c.fk_id, rcv_date
FROM (SELECT @row:=0) r, mytable c
ORDER BY rcv_date

但是——行计数和排序是在整个数据集中完成的。我需要计数在一个共同的 fk_id 内。例如,将返回以下示例数据(第一列表示行数/顺序):
1 | 5 | 2011-10-01
2 | 5 | 2011-10-14
3 | 5 | 2011-11-02
4 | 5 | 2011-12-17
1 | 8 | 2011-09-03
2 | 8 | 2011-11-12
1 | 9 | 2011-10-08
2 | 9 | 2011-10-10
3 | 9 | 2011-11-19

中间一列代表 fk_id。如您所见,排序和行数在 fk_id “分组”内。

更新
我有一个似乎有效的查询,但想要一些关于它是否可以改进的意见:
SELECT IF(@last = c.fk_id, @row:=@row +1, @row:=1) AS ordinality, @last:=c.fk_id, c.fk_id, rcv_date
FROM (SELECT @row:=0) r, (SELECT @last:=0) l, mytable c
ORDER BY c.fk_id, rcv_date

所以它的作用是按 fk_id 和 rcv_date 排序——它基本上处理我的分组。然后我使用第二个变量将前一条记录中的 fk_id 与当前记录进行比较:如果相同,我们增加该行;如果不同,我们重置为 1。

我对真实数据的测试似乎有效。我怀疑这是一个非常低效的查询 - 所以如果有人有改进它的想法,或者看到可能的缺陷,我很乐意听到。

最佳答案

这应该很简单。

SELECT (CASE WHEN @fk <> fk_id THEN @row:=1 ELSE @row:=@row + 1 END) AS ordinality,
       @fk:=fk_id, rcv_date
FROM   (SELECT @row:=0) AS r,
       (SELECT @fk:=0) AS f,
       (SELECT fk_id, rcv_date FROM files ORDER BY fk_id, rcv_date) AS t

我首先通过 fk_id 订购以确保您所有的外键都放在一起(如果它们不在表中怎么办?),然后我做了您喜欢的订购,即通过 rcv_date 。查询检查 fk_id 的变化,如果有变化,则行号变量设置为 1,否则变量递增。它在 case 语句中处理。请注意 @fk:=fk_id 是在大小写检查之后完成的,否则它会影响行号。

编辑: 刚刚注意到您自己的解决方案,恰好与我最终得到的解决方案相同。荣誉! :)

关于mysql - 按列分组的查询结果的行号,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/13216427/

10-12 05:35
查看更多