2010-02-02 6 views
0

J'ai besoin d'une requête SQL qui renvoie les 2 premiers plans par PlanDate par ID client. C'est tout sur une table où PlanID est le PrimaryID, ClientID est un foreignID.Requête SQL, SELECT Top 2 par ordre de clé étrangère par date

C'est ce que j'ai à ce jour ->

SELECT * 
FROM [dbo].[tblPlan] 
WHERE [PlanID] IN (SELECT TOP (2) PlanID FROM [dbo].[tblPlan] ORDER BY [PlanDate] DESC) 

Ceci, évidemment, ne retourne 2 enregistrements où j'ai réellement besoin jusqu'à 2 enregistrements par ClientID.

Répondre

5

Cela peut être fait en utilisant ROW_NUMBER:

SELECT PlanId, ClientId, PlanDate FROM (
    SELECT ROW_NUMBER() OVER (PARTITION BY ClientId ORDER BY PlanDate DESC) rn, * 
    FROM [dbo].[tblPlan] 
) AS T1 
WHERE rn <=2 

Ajouter un produit d'autres colonnes dont vous avez besoin pour les sélectionner.

3

Modifier, décembre 2011. Rectifié CROSS APPLY solution

Essayez les deux pour voir ce qui est mieux

SELECT * 
FROM 
    (-- distinct ClientID values 
    SELECT DISTINCT ClientID 
    FROM [dbo].[tblPlan] 
) P1 
    CROSS APPLY 
    (-- top 2 per ClientID 
    SELECT TOP (2) P2.PlanID 
    FROM [dbo].[tblPlan] P2 
    WHERE P1.ClientID = P2.ClientID 
    ORDER BY P2.[PlanDate] DESC 
) foo 

Ou

;WITH cTE AS (
    SELECT 
    *, 
    ROW_NUMBER() OVER (PARTITION BY clientid ORDER BY [PlanDate] DESC) AS Ranking 
    FROM 
    [dbo].[tblPlan] 
) 
SELECT * FROM cTE WHERE Ranking <= 2 
+0

Hmm, merci mais je reçois ce 'Msg 102, niveau 15, état 1, ligne 5 syntaxe incorrecte près ')'' –

+0

@Refracted Paladin. Mon erreur, alias besoin sur la table "appliquée" – gbn

+0

Intéressant, votre La deuxième option et l'option Mark Byers retournent chacune 7062 lignes. Votre première option renvoie 21948 lignes. Idée sur la disparité? –