如何在SQL中设置相对于组的记录位置?

时间:2016-06-27 21:11:26

标签: mysql sql

我有一系列可以按group_id

分组的记录

示例记录:

╭───╥──────────┬───────────────────╮
│id ║ group_id │ position_in_group │
╞═══╬══════════╪═══════════════════╡
│ 1 ║    2     │        null       │
│ 2 ║    1     │        null       │
│ 3 ║    1     │        null       │
│ 4 ║    1     │        null       │
│ 5 ║    2     │        null       │
│ 6 ║    2     │        null       │
│ 7 ║    3     │        null       │
│ 8 ║    3     │        null       │
│ 9 ║    3     │        null       │
└───╨──────────┴───────────────────┘

我想为每条记录设置position_in_group。如果我GROUP BY group_id,它就是组内记录的位置。

例如:   在ID为1的组中,id = 2的记录是第一个,因此其position_in_group将为1.

决赛桌将是:

╭───╥──────────┬───────────────────╮
│id ║ group_id │ position_in_group │
╞═══╬══════════╪═══════════════════╡
│ 1 ║    2     │        1          │
│ 2 ║    1     │        1          │
│ 3 ║    1     │        2          │
│ 4 ║    1     │        3          │
│ 5 ║    2     │        2          │
│ 6 ║    2     │        3          │
│ 7 ║    3     │        1          │
│ 8 ║    3     │        2          │
│ 9 ║    3     │        3          │
└───╨──────────┴───────────────────┘

我有什么方法可以在SQL查询中执行此操作吗?

4 个答案:

答案 0 :(得分:1)

一种方法是使用变量。在MySQL中有点挑战,但它看起来像这样:

set @g := -1;
set @rn := 0;

update t
    set position_in_group = (@rn := if(@g = group_id, @rn + 1,
                                       if(@g := group_id, 1, 1)
                                      )
                            )
    order by group_id, id;

注意:您需要从update语句中单独初始化变量,因为MySQL在同一update语句中不支持连接和排序。

答案 1 :(得分:0)

无需存储此数据......

create view v_table as
    select b.* 
    from banned b
    where unixtime < UNIX_TIME();

......但如果你真的想......

SELECT id
     , group_id
     , rank
  FROM 
     ( SELECT id
            , group_id
            , CASE WHEN group_id = @prev THEN @i:=@i+1 ELSE @i:=1 END rank 
            , @prev:=group_id prev 
         FROM my_table x
            , (SELECT @i:=1,@prev:=null) vars 
        ORDER 
           BY group_id
            , id
     ) a
 ORDER
    BY id;

答案 2 :(得分:0)

此解决方案由其他用户abcdn实施,请参阅https://stackoverflow.com/a/32105418/3762855

SELECT a.id, a.group_id, (
    SELECT count(*) from groups b where a.id >= b.id AND a.group_id = b.group_id
) AS row_number FROM groups a;

答案 3 :(得分:0)

我找到了一种方法来使用纯SQL执行此操作,并且没有使用自联接的变量:

UPDATE my_table
JOIN (
  SELECT c.aid AS id, COUNT(*)-1 AS position_in_group
  FROM (
    SELECT a.id AS aid, b.id AS bid, a.group_id 
    FROM my_table AS a
    JOIN my_table AS b ON (a.group_id=b.group_id AND a.id >= b.id)
  ) AS c
  GROUP BY c.aid
) AS d ON my_table.id = d.id
SET my_table.position_in_group = d.position_in_group;

我自己加入表格来创建匹配对(同一组中的记录),没有重复对。 然后我只计算那些按左记录的id分组的对。