2008-12-12 7 views

Répondre

3

Si par « précédent » vous voulez dire « l'avant-dernière »:

SELECT TOP 1 
    ordid 
FROM 
    orders 
WHERE 
    custid = @custid 
    and datesold < (SELECT MAX(datesold) FROM orders i where i.custid = orders.custid) 
ORDER BY 
    datesold DESC 

de bien sûr datesold doit être un DATETIME avec des valeurs assez distinctes pour que cela fonctionne. Une date seule ne suffira pas. Si vous avez une date de création d'enregistrement par exemple, ce serait une bonne substitution pour datesold.

1

Une solution commune pour ce genre de problème est de choisir le Max (datesold) et obtenir la dernière de cette façon. C'est correct si la combinaison custid/datesold est unique, mais s'il y avait deux ordres le même jour, cela peut provoquer des doublons.

Si vous avez SQL 2005 ou plus, vous pouvez utiliser la fonction ROW_NUMBER pour classer chaque commandes des clients et sélectionnez la première pour chacun:

SELECT custid, ordid, qty, datesold 
FROM (
    SELECT *, 
     Row_Number() OVER (PARTITION BY custid ORDER BY datesold desc) as 'Rank' 
    FROM tbl 
) 
WHERE Rank = 1 

pour vous assurer qu'il prend toujours le même article, même si ils ont la même date, ajoutez un peu plus d'éléments (tels que RowID, recieptNumber) dans la clause ORDER BY du Row_number.

Si vous n'avez pas SQL 2005, en ajoutant colonne d'identité peut faire des choses similaires:

SELECT custid, ordid, qty, datesold 
FROM tbl 
WHERE id = 
    (SELECT TOP 1 id FROM tbl a WHERE custid = a.custID ORDER BY dateSold) 

L'inconvénient est qu'il y aura une recherche de table au moins pour chaque client, sinon chaque ligne .

Si vous êtes chanceux, vous voulez obtenir la dernière commande traitée, vous pouvez:

SELECT custid, ordid, qty, datesold 
FROM tbl 
INNER JOIN (
    SELECT a.id FROM tbl a GROUP BY tbl.custId 
) s ON tbl.id = s.id 
+0

Comment "ROWNUMBER OVER (... ORDER BY DateSold DESC)" est-il plus correct ou spécifique que "TOP 1 MAX (DateSold)", étant donné que seule la partie date est stockée sur le terrain? Je pense qu'il se comporterait de la même façon: vous donner l'une des lignes correspondantes (la première dans l'ordre du tableau). – Tomalak

+0

Dépend de si DateSold est unique par client ou non –

0

Assomption: Datesold sera dans un ordre ascendant (date de commande précédente sera inférieur à celui actuel)

Disons que vous voulez obtenir l'ordre avant A5 pour le client 2. Voici comment la requête peut être.

 

SELECT TOP 1 * 
FROM Orders 
WHERE DateSold < (SELECT DateSold FROM Orders WHERE CustId = 2 and OrdID = A5) 
AND CustId = 2 
 
+0

Vous aurez besoin d'une clause ORDER BY pour que cela fonctionne correctement –

+0

Tom: où pensez-vous que l'option Order By est nécessaire? – shahkalpesh

+0

À la fin de la requête. Sinon, vous obtenez la première ligne ayant une date antérieure à A5. Ce n'est peut-être pas le dernier rendez-vous. Dans ses exemples de données, il n'y a qu'un autre ordre, mais il ne s'agit que d'un échantillon de données. –

0

Ceci est très similaire à l'autre question que vous avez posée.

SELECT 
    T1.ordid 
FROM 
    dbo.Sales T1 
INNER JOIN dbo.Sales T2 ON 
    T2.custid = T1.custid AND 
    T2.datesold > T1.datesold 
LEFT OUTER JOIN dbo.Sales T3 ON 
    T3.custid = T1.custid AND 
    T3.datesold > T1.datesold AND 
    T3.datesold < T2.datesold 
WHERE 
    T1.custid = @custid AND 
    T3.custid IS NULL 

Mêmes mises en garde concernant les lignes ayant des valeurs de dates identiques.