我有一个包含以下列的表: id | fk_id | rcv_date
可能有多条记录带有常见的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。
我对真实数据的测试似乎有效。我怀疑这是一个非常低效的查询 - 所以如果有人有改进它的想法,或者看到可能的缺陷,我很乐意听到。
答案 0 :(得分:3)
这应该非常简单。
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
在案例检查后完成,否则会影响行号。
编辑:注意到您自己的解决方案恰好与我最终的解决方案相同。奖励! :)