[SQL] besoin d'aide pour une requête

Salut les geeks, j’ai besoin d’aide pour une requête SQL un peu ardue.

Alors j’ai un table suivante:
Company
Score
HistoryNumber qui marche de la façon suivante: 0 est la valeur actuel et les autres valeurs vont de 1 (la valeur la plus vieille) à … autant qu’on veut (la valeur créée juste avant la valeur actuelle)
User: personne qui a calculé le score

Ce que je souhaite faire c’est de sortir un requête qui me sort toutes les valeurs qui ont été calculé par un utilisateur précis et qui sont différente de la valeur précédente dans l’historique.

Par exemple si on a:
Company - Score - HistoryNumber - User
10 - 3 - 0 - user1
10 - 3 - 3 - user1
10 - 6 - 2 - user2
10 - 5 - 1 - user5
20 - 3 - 0 - user1
20 - 3 - 3 - user5
20 - 6 - 2 - user2
20 - 5 - 1 - user2

Et que je cherche le score calculé par user1 et qui sont différent du score précédent ça me sortirait:
10 - 3 - 3 - user1

Une idée comment faire (sous SQL Server)? Moi je bloque un peu.

Sans avoir de quoi tester à portée, essaie un truc du genre :

SELECT DISTINCT user1, score FROM tatable ORDER BY HistoryNumber DESC

Suis rouillé du SQL, donc pas certain qu’elle fasse exactement ce que tu veux, mais on peut affiner, dis-moi déjà ce qu’elle te sort. :slight_smile:

EDIT : Ah attends, mal lu, essaie plutôt ça :

SELECT DISTINCT score FROM tatable WHERE user = leUserVoulu

EDIT 2 : Ouach suis vraiment rouillé, là tu vas avoir toutes les valeurs distinctes de score pour un user, mais pas de notion de chronologie. Je cherche.

Pas moyen de faire ça à l’enregistrement, en ajoutant une colonne type ‘DIFFERE_DU_PRECEDENT’ initialisé à vrai ou à faux selon le cas ?
La requete se fait tranquillou apres ^^

select * from table where user='user1' order by HistoryNumber DESC limit 0,1

Si j’ai bien compris l’enonce, ca doit etre un truc comme ca…

LoneWolf
C’est pas tres complique… :slight_smile:

Après réflexion et squattage d’un collègue, on est tombé d’accord sur le fait qu’il y a une erreur de conception dans ton modèle. :crying:

En effet, le seul moyen de faire ce que tu dis c’est qu’HistoryNumber soit effectivement chronologique et séquentiel. Or là dans les données que tu proposes, il y a des trou. Impossible donc de faire une requête du style « HistoryNumber - 1 » avec comparaison de ligne via requête dans une requête.

Bref les seules solutions (mais on peut se planter) qu’on a à te proposer sont :

  • Faire le tri à l’insertion en allant chercher le dernier résultat inséré pour un user et en le comparant avec celui que tu veux insérer
  • Soit faire une procédure stockée qui te permet d’utiliser des variables
  • Soit rapatrier le boulot au niveau code (ce qui revient un peu au même simple question d’architecture et choix organisationnels)
  • Soit revoir ton modèle pour l’adapter à tes besoins.

LoneWolf : T’as compris sensiblement la même chose que moi au début, mais en fait non c’est pas ça. :slight_smile:

Je comprend pas non plus où est le problème. Gynsu, si aucune solution proposée ne te donne satisfaction, tu pourrais étayer ton exemple ? Je pense que rajouter une ligne d’enregistrement pour user1 de la company 10 permettrait de mieux cerner ou tu veux en venir.

Et je comprend pas comment vous en êtes arrivés à dire que 0 c’est la dernière version plutôt que la plus grande.

(Sinon Lonewolf, pour ta culture, LIMIT ca existe pas sous SQL Server)

Vite fait (pas testé), et si j’ai bien compris, tu ne peux pas utiliser des fonctions analytiques ?

[codebox]select compagny, historynumber, score, user from
(select lag(score,1) over(partition by compagny order by HistoryNumber) lastscore,
score,
compagny,
historynumber,
user
from matable
)
where score != lastscore and user = user1[/codebox]

Cette requête ne marche pas parce que l’historynumber ne suit pas un ordre chronologique numérique (0 est plus récent que 1 mais 1 est plus vieux que 2). Mais ça peut donner une piste.

Je pense que c’est pour avoir une requête simple qui permette d’avoir la note « courante » en récupérant les lignes = 0.

Sinon je vois pas sans faire une sous requete par ligne potentielle (donc perfs horribles, n²).

Si ta requête fonctionne Crocobill, suffit de préciser DESC au niveau du order by pour régler le soucis.

Donc y a ptet une solution finalement. :slight_smile:

bon, en fait j’ai trouvé ce qu’il me faut. C’est tout con:

SELECT * FROM scoretable t1 WHERE user='user1' AND score<>(SELECT score FROM scoretable t2 WHERE t1.company=t2.company AND t2.historynumber=t1.historynumber-1)
Bon j’omets volontairement le score actuel: le background de la recherche fait qu’il est peut probable qu’on trouve des valeurs recherchées (et au final je perd trop de temps sur un petit problème à la con qui n’en vaut pas la peine). Au pire je pourrais faire une requête spécifique pour la clause historynumber=0

C’est pour une question de performance: lorsque tu veux faire des requêtes sur les valeurs actuelles tu fait un simple

WHERE historynumber=0

plutôt qu’un

WHERE historynumber=(SELECT MAX(historynumber) FROM score WHERE company=X)

Et lorsque tu insères une nouvelle valeur tu fais un update tout simplement de la valeur actuelle avant d’insérer la nouvelle entrée:

UPDATE score SET historynumber=(SELECT MAX(historynumber) FROM score WHERE company=X)

Néanmoins merci pour vos réponses, je vous ai dérangé un peu pour rien en fait :slight_smile:

[quote=“Gynsu2000, post:10, topic: 37962”]C’est pour une question de performance: lorsque tu veux faire des requêtes sur les valeurs actuelles tu fait un simple

plutôt qu’un

Et lorsque tu insères une nouvelle valeur tu fais un update tout simplement de la valeur actuelle avant d’insérer la nouvelle entrée:

Néanmoins merci pour vos réponses, je vous ai dérangé un peu pour rien en fait :)[/quote]

Oh OK, bon à savoir si j’ai un besoin du genre un jour :crying:

Je viens de tester et ma requête fonctionne donc avec une bidouille por régler le problème du 0 ça donne :

[codebox]select compagny, historynumber, score, user from
(select lag(score,1)
over(partition by compagny
order by decode(historynumber,0,null,historynumber) nulls last) lastscore,
score,
compagny,
historynumber,
user
from matable
)
where score != lastscore and user = user1[/codebox]

EDIT : Je suis c**, pas besoin de faire une autre sous-vue.

Ca c’est la requête que j’allais te proposer. Mais elle va planter si il y a des trou dans tes données (comme expliqué plus haut, si HistoryNumber-1 n’existe pas, comme c’est le cas dans les données que tu proposes).

EDIT : C’était en réponse à Gynsu

[quote=“Molokai, post:13, topic: 37962”]Ca c’est la requête que j’allais te proposer. Mais elle va planter si il y a des trou dans tes données (comme expliqué plus haut, si HistoryNumber-1 n’existe pas, comme c’est le cas dans les données que tu proposes).

EDIT : C’était en réponse à Gynsu[/quote]
Je pense que son exemple de données excluait involontairement des n°.

[quote=« Gynsu2000, post:10, topic: 37962 »][…]Et lorsque tu insères une nouvelle valeur tu fais un update tout simplement de la valeur actuelle avant d’insérer la nouvelle entrée:

UPDATE score SET historynumber=(SELECT MAX(historynumber) FROM score WHERE company=X)

[…][/quote]
Attention, juste pour info, si tu fais vraiment cette requête, je crois que tu vas avoir du mal à utiliser historynumber ensuite… :slight_smile: