3

我有一个包含以下列的表: 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。

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

4

1 回答 1

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

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

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

于 2012-11-04T06:58:42.863 回答