[英]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.