2010-09-09 17 views
5

J'essaie d'envelopper ma tête autour de celle-ci ce matin.Énigme SQL, comment sélectionner la dernière date pour une pièce, mais seulement 1 rangée par pièce (unique)

J'essaie de montrer inventory statut pour les pièces (pour nos produits) et cette requête devient seulement complexe si j'essaye de renvoyer toutes les pièces.

Permettez-moi étalez:

  • seule table inventoryReport
  • J'ai une liste distincte des parties X Je souhaite afficher, dont le résultat doit être X # de lignes (1 ligne par partie montrant la dernière entrée de l'inventaire).
  • Le tableau est constitué d'entrées datées de changements d'inventaire (donc j'ai seulement besoin de l'entrée de date LATEST par pièce).
  • toutes les données contenues dans cette table unique, donc pas de jointures nécessaires.

Actuellement pour 1 seule pièce, il est assez simple et je peux accomplir cela en faisant la requête SQL suivante (pour vous donner une idée):

SELECT  TOP (1) ldDate, ptProdLine, inPart, inSite, inAbc, ptUm, inQtyOh + inQtyNonet AS in_qty_oh, inQtyAvail, inQtyNonet, ldCustConsignQty, inSuppConsignQty 
FROM   inventoryReport 
WHERE  (ldPart = 'ABC123') 
ORDER BY ldDate DESC 

qui me fait mon TOP 1 rang, donc simple par partie, cependant je dois montrer tout X (disons 30 parties). J'ai donc besoin de 30 lignes, avec ce résultat. Bien sûr, la solution simple serait de boucler X # d'appels sql dans mon code (mais cela serait coûteux) et cela suffirait, mais à cet effet, j'aimerais travailler sur ce SQL encore plus pour réduire les appels x # à la db (si non nécessaire) jusqu'à 1 requête. D'après ce que je peux voir ici, j'ai besoin de garder une trace de la dernière date par article en quelque sorte tout en cherchant mon jeu de résultats.

Je finalement faire une

WHERE ldPart in ('ABC123', 'BFD21', 'AA123', etc) 

pour limiter les pièces dont j'ai besoin. J'espère avoir suffisamment clarifié ma question. Faites-moi savoir si vous avez une idée. Je ne peux pas faire un DISTINCT car les lignes ne sont pas les mêmes, la date doit être la dernière, et j'ai besoin d'un maximum de X lignes.

Pensées? Je suis coincé ...

Répondre

2

EDIT: Assurez-vous de tester les performances de chaque solution. Comme indiqué dans this question, la méthode CTE peut surpasser en utilisant ROW_NUMBER.

;with cteMaxDate as (
    select ldPart, max(ldDate) as MaxDate 
     from inventoryReport 
     group by ldPart 
) 
SELECT md.MaxDate, ir.ptProdLine, ir.inPart, ir.inSite, ir.inAbc, ir.ptUm, ir.inQtyOh + ir.inQtyNonet AS in_qty_oh, ir.inQtyAvail, ir.inQtyNonet, ir.ldCustConsignQty, ir.inSuppConsignQty 
    FROM cteMaxDate md 
     INNER JOIN inventoryReport ir 
      on md.ldPart = ir.ldPart 
       and md.MaxDate = ir.ldDate 
5
SELECT * 
    FROM (SELECT i.*, 
     ROW_NUMBER() OVER(PARTITION BY ldPart ORDER BY ldDate DESC) r 
     FROM inventoryReport i 
     WHERE ldPart in ('ABC123', 'BFD21', 'AA123', etc) 
     ) 
    WHERE r = 1 
2

Vous devez joindre à une sous-requête:

SELECT i.ldPart, x.LastDate, i.inAbc 
FROM inventoryReport i 
INNER JOIN (Select ldPart, Max(ldDate) As LastDate FROM inventoryReport GROUP BY ldPart) x 
on i.ldPart = x.ldPart and i.ldDate = x.LastDate