2008-10-14 8 views
5

Je cherche un moyen de numéroter séquentiellement des lignes dans un jeu de résultats (pas une table). Essentiellement, je commence avec une requête comme suit:Technique Pure-SQL pour les lignes de numérotation automatique dans le jeu de résultats

SELECT id, name FROM people WHERE name = 'Spiewak' 

Les id s ne sont évidemment pas une vraie séquence (par exemple 1, 2, 3, 4). Ce dont j'ai besoin, c'est d'une autre colonne dans le jeu de résultats qui contient ces auto-numérotations. Je suis prêt à utiliser une fonction SQL si je le dois, mais je préfère le faire sans utiliser d'extension sur la spécification ANSI.

Plate-forme est MySQL, mais la technique devrait être multi-plateforme si possible (d'où le désir d'éviter les extensions non-standard).

Répondre

9

Pour avoir un nombre significatif de ligne que vous devez commander vos résultats. Ensuite, vous pouvez faire quelque chose comme ceci:

SELECT id, name 
    , (SELECT COUNT(*) FROM people p2 WHERE name='Spiewak' AND p2.id <= p1.id) AS RowNumber 
FROM people p1 
WHERE name = 'Spiewak' 
ORDER BY id 

Notez que la clause WHERE de la sous requête doit correspondre à la clause WHERE ou la clé primaire de la requête principale et ORDER BY de la requête principale.

SQL Server a la construction ROW_NUMBER() OVER pour simplifier cela, mais je ne sais pas si MySQL a quelque chose de spécial pour l'adresser.


Depuis mon post ici a été accepté comme réponse, je veux appeler aussi la réponse de Dan Goldstein, qui est très similaire dans l'approche, mais utilise un JOIN au lieu d'une sous requête et souvent de meilleures performances

+1

C'est intelligent, mais la performance doit être HORRIBLE. Pas que je dise qu'il y ait une meilleure réponse, juste frémir au O (n^2). –

+0

Wow! C'est très intelligent. Je ne savais même pas que vous pouviez utiliser des sous-requêtes pour définir les champs res de cette façon. –

+0

D'accord que la performance pourrait être meilleure, mais si vous êtes limité à ansi c'est ce que vous avez à faire. Parfois, les gens vont pré-calculer ces résultats pour accélérer les choses. –

2

Il n'y a pas de façon standard ANSI de le faire dont je suis conscient.

Dans SQL Server, vous disposez d'une fonction ROW_NUMBER() qui peut être utilisée et dans Oracle, il existe une pseudo-colonne ROWNUM.

Dans MySQL, il y a this technique

+0

Il préfèrerait probablement ROW_NUMBER() à RANK() pour cela, mais comme il utilise MySQL/Ansi, c'est un point discutable. –

7

Une idée qui est assez inefficace, mais est la norme ANSI SQL serait de compter le nombre de lignes avec un identifiant moindre correspondant aux mêmes critères. Je n'ai pas testé ce SQL et cela ne fonctionnera probablement pas, mais quelque chose comme:

SELECT id, name, sub.lcount 
FROM people outer 
JOIN (SELECT id, COUNT(id) lcount FROM people WHERE name = 'Spiewak' AND id < outer.id GROUP BY id) sub on outer.id = sub.id 
WHERE name = 'Spiewak' 
+0

Fondamentalement la même chose que ce que j'ai posté, mais le JOIN sera probablement plus rapide que la sous-requête pour la plupart des cas. –

+0

Oh, vous avez toujours besoin d'une commande explicite sur votre requête externe ou cela peut renvoyer des résultats ordonnés différemment de la requête. –

-1

Pour le serveur SQL, consultez la fonction RANK.

2

Dans Oracle la seule base de données, je sais ce que vous voulez faire est de faire un sous sélectionner les données

-à-dire

select rownum, id , blah, blah 
from (
select id, name FROM people WHERE name = 'Spiewak' 
) 

le concept de base est que le rownum seront évaluées sur le jeu de résultats renvoyé par le select interne. J'espère que cela pourrait vous diriger vers une solution que vous pouvez utiliser.

1

Je sais que c'est un vieux fil, mais je cherchais juste maintenant cette réponse. J'ai essayé la requête de Dan Goldstein dans MySQL, mais cela n'a pas fonctionné comme écrit car 'outer' est un mot réservé. Ensuite, j'ai remarqué qu'il utilise toujours une sous-requête, de toute façon.

Alors, je me suis dit une version à l'aide JOIN, mais pas de sous-requête:

SELECT SUM(IF(p1.id > p2.id, 0, 1)) AS `row`, p2.id, p2.name 
    FROM people p1 JOIN people p2 ON p1.name = p2.name 
    WHERE p1.name = 'Spiewak' 
    GROUP BY p2.id 

Cela a fonctionné pour moi dans MySQL 5.1. Pour MySQL, il semble suffire de GROUP BY p2.id. Un ORDER BY p2.id explicite peut être ajouté à la fin de la requête, mais j'ai obtenu les mêmes résultats, de toute façon.

Questions connexes