2016-06-27 5 views
0

Ich habe eine Reihe von Datensätzen, die von einem group_idWie setze ich die Position des Datensatzes relativ zu einer Gruppe in SQL?

Beispiel Datensätze gruppiert werden können:

╭───╥──────────┬───────────────────╮ 
│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  │ 
└───╨──────────┴───────────────────┘ 

ich die position_in_group für jeden Datensatz festlegen möchten. Es ist die Position des Datensatzes innerhalb der Gruppe, wenn ich GROUP BY group_id.

Zum Beispiel: In der Gruppe mit der ID 1, die Platte mit id = 2 ist die erste, so dass ihre position_in_group würde 1.

Der Finaltisch sei sein:

╭───╥──────────┬───────────────────╮ 
│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   │ 
└───╨──────────┴───────────────────┘ 

Ist kann ich das irgendwie in einer SQL-Abfrage machen?

+2

Dies würde erfolgen mit 'row_number() über (Partition von group_id Reihenfolge nach ID) 'in Oracle und Sqlserver. Überprüfen Sie hier für mysql gleichwertige Optionen: http://StackOverflow.com/q/1895110/6205293 – mo2

+0

Ja, eine Abfrage mit Variablen (@ 's) ... jemand knallt eins aus. – Drew

Antwort

0

Ich fand einen Weg, um dies mit reinem SQL und ohne Variablen mit zu tun ein selbst 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; 

I selbst verbinden sich mit den Tabellen passende Paare (Datensätze in der gleichen Gruppe) ohne doppelte Paare zu erstellen. Dann zähle ich nur diese Paare Gruppierung nach der ID des linken Datensatzes.

1

Eine Methode ist die Verwendung von Variablen. Ein bisschen in MySQL herausfordernd, aber es kann wie folgt aussehen:

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; 

Hinweis: Sie müssen die Variablen getrennt von der update Anweisung initialisieren, weil MySQL nicht unterstützt verbinden und um durch in der gleichen update Aussage.

0

Es gibt keine Notwendigkeit, diese Daten zu speichern ...

SELECT id 
    , group_id 
    , rank 
    FROM 
    (SELECT id 
      , group_id 
      , CASE WHEN group_id = @prev THEN @i:[email protected]+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; 

... aber wenn Sie wirklich wollen ...

UPDATE my_table a 
    JOIN 
    (SELECT id 
      , group_id 
      , CASE WHEN group_id = @prev THEN @i:[email protected]+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; 
0

diese Lösung von einem anderen Benutzer implementiert wurde abcdn sehen 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; 
Verwandte Themen