2017-08-22 4 views
2

j'ai 4 instructions select:Combiner sélectionner top 1 des instructions SQL

SELECT top 1 software, auditDate, versionNumber FROM table1 where software = 'software1' order by auditDate desc 
SELECT top 1 software, auditDate, versionNumber FROM table1 where software = 'software2' order by auditDate desc 
SELECT top 1 software, auditDate, versionNumber FROM table1 where software = 'software3' order by auditDate desc 
SELECT top 1 software, auditDate, versionNumber FROM table1 where software = 'software4' order by auditDate desc 

Actuellement, chaque instruction select retourne une table avec une ligne comme celle-ci:

software | auditDate | versionNumber 
1| software1 | 8/22/2017 | 5.0 

Si la condition top 1 n'a pas été là, alors la table de résultat aurait plus de lignes du même logiciel avec différents auditDate et versionNumber, mais j'avais seulement besoin de l'enregistrement le plus récent (auditDate) pour chaque logiciel.

Je voudrais rouler toutes ces instructions select dans une requête qui retourne un tableau similaire à ceci:

software | auditDate | versionNumber 
1| software1 | 8/22/2017 | 5.0 
2| software2 | 8/20/2017 | 5.3 
3| software3 | 8/21/2017 | 4.9 
4| software4 | 8/16/2017 | 5.6 

où chaque ligne est la même que la déclaration individuelle select top 1 ci-dessus. Un UNION ne semble pas fonctionner à cause de la clause order by et je suis perplexe pour d'autres solutions.

Répondre

6

Une autre option utilise le AVEC TIES clause

Select top 1 with ties 
     software, auditDate, versionNumber 
From table1 
Where software IN ('software1','software2','software3','software4') 
Order By Row_Number() over (Partition By software Order By auditDate Desc) 
+0

Si je comprends bien, le générique pour ceci est «Top N with ties» et doit être accompagné d'une clause «order by». Je ne comprends pas la partie «Partition», pourriez-vous donner quelques explications? – CuriousOne

+0

@CuriousOne Cette approche ne génère pas de champ supplémentaire comme l'approche CTE. Row_Number() est une fonction de fenêtre, elle va générer une séquence de nombres 1 - n "réinitialisation" pour chaque logiciel, ordre par la date décroissante. Si vous n'êtes pas à l'aise avec les fonctions de la fenêtre, cela vaut la peine d'expérimenter. Ils peuvent être inestimables! –

+1

Merci pour la clarification. Je ne suis pas trop expérimenté avec SQL mais quand je commencerai mon étude en profondeur, je me souviendrai de faire des recherches sur les fonctions de cette fenêtre. :) – CuriousOne

6

Vous pouvez utiliser ROW_NUMBER:

WITH CTE AS 
(
    SELECT *, 
      RN = ROW_NUMBER() OVER(PARTITION BY software ORDER BY auditDate DESC) 
    FROM dbo.table1 
    WHERE software IN ('software1','software2','software3','software4') 
) 
SELECT * 
FROM CTE 
WHERE RN = 1; 
+0

Bien que cela fournisse techniquement les enregistrements dont j'ai besoin, cela produit des colonnes supplémentaires à partir de la table 1 qui gâcheraient ma sortie, mais je vous remercie pour la suggestion. – CuriousOne

+0

@CuriousOne yup, mais, je veux dire, vous savez peut sélectionner les colonnes que vous voulez, non? – Lamak

0

En supposant que vous avez un col identifiant et ne voulez pas nommer l'utilisation du logiciel quelque chose comme:

Sélectionnez * à partir de ((Sélectionnez l'ID, le logiciel, max (auditDate) du groupe table1 par ID, le logiciel) a Table de jointure à gauche 1 b sur a.id = b.id)