2009-06-09 9 views
1

Supposons que j'ai une table nommée [ProductPriceHistory] comme ce qui suit:SQL - Problème avec SQL Query; groupe par et rejoindre

 
HistoryID..ProductCode..EffectDate.... Price.... IsActive...ProductName 
1----------11-----------1 Jan 09-------100-------true-------AAA 
2----------11-----------1 Feb 09-------150-------true-------AAA 
3----------11-----------1 Mar 09-------200-------false------AAA 
4----------22-----------1 Jan 09-------150-------true-------BBB 
5----------22-----------1 Feb 09-------200-------true-------BBB 
6----------22-----------1 Mr 09--------250-------true-------AAA 

Comment puis-je trouver le statut final de tous les produits actifs sur le dernier jour?

C'est, ma requête trouvera la ligne:

6----------22-----------1 Mr 09--------250-------true-------AAA

Répondre

1

pour obtenir l'utilisation donnée de la valeur du code produit:

DECLARE @ProcuctCode int 
SET @ProductCode=11 

SELECT 
    h.* 
    FROM ProductPriceHistory h 
     INNER JOIN (SELECT 
         ProductCode 
          ,MAX(EffectDate) AS MaxEffectDate 
         FROM ProductPriceHistory 
         WHERE Pr[email protected] 
          AND IsActive='true' 
         GROUP BY ProductCode 
        ) dt ON h.ProductCode=dt.ProductCode AND h.EffectDate=dt.MaxEffectDate 
    WHERE h.ProductCode [email protected] 

pour trouver tous les produits utilisent:

SELECT 
    h.* 
    FROM ProductPriceHistory h 
     INNER JOIN (SELECT 
         ProductCode 
          ,MAX(EffectDate) AS MaxEffectDate 
         FROM ProductPriceHistory 
         WHERE IsActive='true' 
         GROUP BY ProductCode 
        ) dt ON h.ProductCode=dt.ProductCode AND h.EffectDate=dt.MaxEffectDate 
    ORDER BY h.ProductCode 
+0

Cela semble bien, mais vous devez mettre un h.IsActive = 'true' quelque part. +1 – wcm

+0

@wcm, la table dérivée contient IsActive = 'true', et celle-ci sera ensuite jointe à la ligne appropriée, donc pas besoin de faire autre chose ... –

+0

@KM, Si vous supposez que ProductCode et EffectiveDate sont uniques alors tu as raison. C'est probablement ce que voulait dire JMSA, donc je concède le point. – wcm

2
select * from ProductPriceHistory p1 
where EffectDate = 
(select max(EffectDate) from ProductPriceHistory p2 
where p1.ProductCode = p2.ProductCode and p2.EffectDate<=getdate()) 
+0

Avez-vous oublié 'IsActive = true? –

+0

Vous avez également oublié GROUP BY ... !!! –

+1

@jmsa - n'a pas besoin d'être groupé si toutes les colonnes référencées (effectivedate) sont passées dans la fonction d'agrégat (ce qui est le cas). C'est la solution typique pour ce genre de problème, mais notez que si vous n'avez pas une contrainte unique de EffectDate, vous obtiendrez des lignes dupliquées en sortie. – ahains

1

vous n'êtes pas tout à fait spécifier complètement - peut-être la requête de @tekBlues est ce que vous voulez, ou peut-être:

SELECT * FROM ProductPriceHistory t1 
WHERE t1.EffectDate = 
    (SELECT MAX(t2.EffectDate) 
    FROM ProductPriceHistory t2 
    WHERE t2.IsActive=true) 
    AND t1.IsActive=true 
0

en supposant que ProductCode et EffectDate identifient une ligne, vous pouvez faire:

SELECT * 
    FROM productpricehistory 
    , (SELECT productcode 
      , MAX(effectdate) effectdate 
      FROM productpricehistory 
     GROUP BY productcode) maxhistory 
WHERE productpricehistory.productcode = maxhistory.productcode 
    AND productpricehistory.effectdate = maxhistory.effectdate 
    AND IsActive = TRUE; 

Si ProductCode et EffectDate n'identifient pas de manière unique une ligne, vous voudrez probablement utiliser HistoryId au lieu de EffectDate, si nous pouvons supposer que HistoryId est unique et qu'un HistoryId croissant signifie également un EffectDate croissant. Edit: Je me rendais compte que je traitais l'actif différemment de ce que vous étiez - je supposais que IsActive ne s'appliquait qu'à l'EffectDate, mais je vois que vous désactivez un produit entier en définissant son "IsActive" sur false. J'ai mis à jour en conséquence, en supposant que vous pourriez ensuite activer un produit en créant une nouvelle ligne avec IsActive = true.