2010-07-21 3 views
1

J'ai une table qui suit les numéros de série et le nombre de licences associées à ce numéro de série. Un client peut renouveler la licence d'une boîte, en augmentant ou en diminuant le nombre d'utilisateurs, et ils sont facturés uniquement pour le montant modifié.SQL Group Par question - choisir quelle ligne est regroupée

La structure de la table suivante existe:

id - Auto Incrementing ID 
serial - The serial number 
numusers - the number of licenses 
date - The date that the request was submitted, with the highest date being the number of users currently licensed 

J'ai la requête suivante pour sélectionner les licences qui ont été mises à jour, et il fonctionne si la licence n'a été présenté à nouveau une fois. Si elle a été soumise à plusieurs reprises, elle renvoie des références à la mise à jour précédente et à toutes les mises à jour antérieures.

SELECT p.id as id, c.id as oldid, p.numusers-c.numusers AS dif, p.date, c.date 
FROM `licenses` AS p 
JOIN `licenses` AS c ON p.serial = c.serial 
        AND p.date > c.date 
        AND p.id <> c.id 
WHERE p.id = 156 
#GROUP BY p.id 

Voici l'ensemble de données:

id serial numusers date 
26 1234 500   2010-07-14 
34 1234 600   2010-07-15 
156 1234 500   2010-07-21 

Quand je lance la requête, je reçois le texte suivant:

id  oldid  dif   date   date 
156  26   0   2010-07-21 2010-07-14 
156  34   -100  2010-07-21 2010-07-15 

Si je décommenter la clause GROUP BY dans la requête, je reçois la rangée avec l'oldid de 26. Comment est-ce que je sélectionnerais seulement la rangée avec la date la plus récente (rangée avec oldid de 34)? Je pourrais employer ORDER BY et LIMIT 1, mais je veux également pouvoir choisir de la table entière sans clause de WHERE. J'utilise MySQL 5.1.

Répondre

1

Peut-être ce que vous voulez est:

select p.id, c.id as priorid, p.numusers-c.numusers AS dif, p.date, c.date as priordate  
from licenses p 
join licenses c on c.serial=p.serial 
    and c.date=(select max(date) from licenses ref where ref.serial=p.serial 
    and ref.date<p.date) 
order by p.serial 

Je l'ai toujours trouvé une limitation assez ennuyeux de SQL que dire « me obtenir le champ X du dossier avec le La valeur max pour le champ Y "nécessite que je lise la table une fois pour trouver la valeur maximale de Y avec une requête incorporée, puis la relise pour retrouver l'enregistrement avec cette valeur et récupérer les autres valeurs que je veux.

S'il y a trois enregistrements pour la même série, les éléments ci-dessus doivent indiquer deux lignes de "différence" sur la sortie. Je pense que c'est ce que vous dites que vous voulez. S'il n'y a qu'un seul enregistrement pour une série donnée, ce qui précède ne donnera aucune sortie pour cette série, ce qui peut être ce que vous voulez et peut-être pas.

+0

C'est exactement ce que je voulais, merci. Je me suis dit qu'il existait une méthode SQL plus simple pour "obtenir le champ X de l'enregistrement avec la valeur maximale pour le champ Y" mais je suppose que non. – HalfBrian

1

Une table dérivée serait utile; quelque chose comme ...

SELECT * 
    FROM (SELECT p.id as id, 
       c.id as oldid, 
       p.numusers-c.numusers AS dif, 
       p.date, 
       c.date 
       FROM `licenses` AS p JOIN `licenses` AS c ON p.serial = c.serial 
        AND p.date > c.date 
        AND p.id <> c.id 
       ORDER BY oldid DESC) AS inner_table 
    GROUP BY id;