簡體   English   中英

如何在SQL中設置記錄相對於組的位置?

[英]How do I set the record's position relative to a group in SQL?

我有一系列可以按group_id分組的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 如果I 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查詢中執行此操作?

一種方法是使用變量。 在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語句中進行聯接和排序。

無需存儲此數據...

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;

...但是如果您真的想...

UPDATE my_table a
  JOIN 
     ( 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
     ) b
    ON b.id = a.id
   SET a.rank = b.rank;

此解決方案是由另一個用戶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;

我發現了一種使用純SQL且不使用自JOIN變量的方法來做到這一點:

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對那些對進行分組。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM