2008-11-02 6 views
1

Voici un scénario simple avec des personnages de table:MySQL: obtenir des différences de chaque colonne triée en jeu de lignes

CharacterName GameTime Gold Live 
Foo 10 100 3 
Foo 20 100 2 
Foo 30 95 2 

Comment puis-je obtenir cette sortie pour la requête SELECT Gold, Live FROM characters WHERE name = 'Foo' ORDER BY GameTime:

Gold Live 
100 3 
0 -1 
-5 0 

utilisant MySQL procédure stockée (ou requête) si c'est encore possible? J'ai pensé à utiliser 2 tableaux comme ce que l'on ferait normalement dans un langage côté serveur, mais MySQL n'a pas de types de tableaux. Bien que je sache que c'est probablement plus facile à faire en PHP (mon langage côté serveur), je veux savoir s'il est possible de le faire en MySQL, juste comme un matériel d'apprentissage.

+0

Je comprends l'avant et l'après mais je suppose que je ne vois pas comment une table arrive à l'autre. Pour quelle raison les deuxième et troisième rangs perdent-ils 100 pièces d'or et qu'est-ce qui leur fait perdre des vies? –

+0

@Stephen, je pense que SyaZ veut que chaque ligne montre juste les différences à la rangée précédente. –

+0

Exactement Romulo. La nouvelle ligne montre les différences entre elle et la rangée précédente. – syaz

Répondre

1

Une solution possible en utilisant une table temporaire:

CREATE TABLE characters_by_gametime (
    id INTEGER AUTO_INCREMENT PRIMARY KEY, 
    gold INTEGER, 
    live INTEGER); 

INSERT INTO characters_by_gametime (gold, live) 
SELECT gold, live 
FROM characters 
ORDER BY game_time; 

SELECT 
    c1.id, 
    c1.gold - IFNULL(c2.gold, 0) AS gold, 
    c1.live - IFNULL(c2.live, 0) AS live 
FROM 
    characters_by_gametime c1 
    LEFT JOIN characters_by_gametime c2 
    ON c1.id = c2.id + 1 
ORDER BY 
    c1.id; 

Bien sûr, la solution de Eoin est mieux si votre colonne id suit l'ordre que vous voulez dans la sortie.

+0

Bon point. En effet, vous auriez besoin de construire une table temporaire avec une séquence d'ID contiguë si elle n'existait pas déjà. –

2

Avez-vous un identifiant sur votre table?

GameID  CharacterName GameTime Gold  Live 
----------- ------------- ----------- ----------- ----------- 
1   Foo   10   100   3 
2   Foo   20   100   2 
3   Foo   30   95   2 

Si oui, vous pourriez faire une jointure décalée sur lui-même

SELECT 
    c.CharacterName, 
    CASE WHEN c_offset.Gold IS NOT NULL THEN c.Gold - c_offset.Gold ELSE c.Gold END AS Gold, 
    CASE WHEN c_offset.Live IS NOT NULL THEN c.Live - c_offset.Live ELSE c.Live END AS Live 
FROM Characters c 
    LEFT OUTER JOIN Characters c_offset 
     ON c.GameID - 1 = c_offSet.GameID 
ORDER BY 
    c.GameTime 

Essentiellement, il se joint à chaque ligne de jeu à la ligne précédente de jeu et fait un diff entre les valeurs. Cela renvoie le suivant pour moi.

CharacterName Gold  Live 
------------- ----------- ----------- 
Foo   100   3 
Foo   0   -1 
Foo   -5   0 
+0

Cela suppose que les ID seraient séquentiels, sans ID manquants, etc. L'utilisation d'une sous-requête pour récupérer l'ID/GameTime de la ligne précédente permettrait de résoudre ce problème. À part ça ... c'est comme ça que je le ferais. – Tomalak

+0

@Tomalak, mais comment obtenez-vous la ligne précédente avec MySQL? Je pense que vous auriez besoin d'une fonction similaire à ROW_NUMBER(), mais elle n'existe pas. –

Questions connexes