2009-10-09 7 views
0

En regardant les questions connexes, je ne pense pas que cette question spécifique a été posée, alors voilà.Comment puis-je utiliser Group By (au lieu d'auto-jointures) pour obtenir les données correctes (exemple spécifique inclus)

J'ai eu une situation où je me suis joint à une table trois fois pour obtenir des données différentes en fonction des dates.

Cela prend trop de temps, donc dans le but d'optimiser, je réécrite en utilisant un groupe tel que défini par ici: http://weblogs.sqlteam.com/jeffs/jeffs/archive/2007/06/12/60230.aspx

Je vais avoir du mal avec la logique, et je commence à penser il n'est pas possible d'obtenir exactement ce que je veux par là. Je vais vous montrer mon code actuel puis décrire ce dont j'ai besoin (tables/variables modifiées pour protéger l'innocent).

SELECT 
upc, 
MAX(CASE WHEN ip_start_date <= GETDATE() THEN ip_unit_price END) AS retail_amount, 
MAX(CASE WHEN ip_start_date <= GETDATE() THEN ip_price_multiple END) AS retail_multiplier_num,  
MAX(CASE WHEN ip_start_date BETWEEN GETDATE() AND DATEADD(ww,1,GETDATE()) THEN ip_unit_price END) AS retail_amt_nxt_wk, 
MAX(CASE WHEN ip_start_date BETWEEN GETDATE() AND DATEADD(ww,1,GETDATE()) THEN ip_price_multiple END) AS retail_multipler_num_nxt_wk, 
MAX(CASE WHEN ip_start_date BETWEEN DATEADD(ww,1,GETDATE()) AND DATEADD(ww,2,GETDATE()) THEN ip_unit_price END) AS retail_amt_wk_after_nxt, 
MAX(CASE WHEN ip_start_date BETWEEN DATEADD(ww,1,GETDATE()) AND DATEADD(ww,2,GETDATE()) THEN ip_price_multiple END) AS retail_multiplier_num_wk_after_nxt 
FROM 
items AS im WITH (NOLOCK) 
    retails AS ip WITH (NOLOCK) 
    ON im.ID = ip.ID 
GROUP BY 
upc 

Donc, en regardant la première ligne, cela me donne le maximum de détail avec une date moins qu'aujourd'hui. J'ai vraiment besoin de la plus récente, pas la plus grande. Cela a été utilisé avec une sous-requête qui m'a obtenu le MAX (start_date) moins qu'aujourd'hui. Je ne peux pas faire un MAX dans un MAX, pour ce qui sont probablement de bonnes raisons. Je pensais à DERNIER, mais je ne suis pas sûr que le dernier enregistrement sera toujours le plus récent dans notre système (nouveau système).

Est-ce que quelqu'un voit une solution à cela? Les BETWEENS fonctionnent bien, MAX Retail dans cette semaine est assez bon que ceux qui sont pour l'estimation. L'autre doit être précis, cependant.

(Ne hésitez pas à modifier title..I ne pouvait pas trouver une façon succincte de poser)

Répondre

1

En SQL Server 2005+:

SELECT upc, retail_today.*, retail_next_week.*, retail_two_weeks.* 
FROM items im 
OUTER APPLY 
     (
     SELECT TOP 1 
       ip_unit_price, ip_price_multiple 
     FROM retail ip 
     WHERE ip.ip_start_date <= GETDATE() 
       AND ip.id = im.id 
     ORDER BY 
       ip_start_date DESC 
     ) retail_today 
OUTER APPLY 
     (
     SELECT TOP 1 
       ip_unit_price, ip_price_multiple 
     FROM retail ip 
     WHERE ip.ip_start_date BETWEEN GETDATE() AND DATEADD(ww, 1, GETDATE()) 
       AND ip.id = im.id 
     ORDER BY 
       ip_start_date DESC 
     ) retail_next_week 
OUTER APPLY 
     (
     SELECT TOP 1 
       ip_unit_price, ip_price_multiple 
     FROM retail ip 
     WHERE ip.ip_start_date BETWEEN DATEADD(ww, 1, GETDATE()) AND DATEADD(ww, 2, GETDATE()) 
       AND ip.id = im.id 
     ORDER BY 
       ip_start_date DESC 
     ) retail_two_weeks 

En SQL Server 2000:

SELECT upc, 
     (
     SELECT TOP 1 
       ip_price 
     FROM retail ip 
     WHERE ip.ip_start_date <= GETDATE() 
       AND ip.id = im.id 
     ORDER BY 
       ip_start_date DESC 
     ) AS ip_price_today, 
     (
     SELECT TOP 1 
       ip_price_multiple 
     FROM retail ip 
     WHERE ip.ip_start_date <= GETDATE() 
       AND ip.id = im.id 
     ORDER BY 
       ip_start_date DESC 
     ) AS ip_price_multiple_today, 
     … 
FROM items im 
+0

Merci pour la réponse rapide. Je vais essayer et vous faire savoir comment ça fonctionne. – IronicMuffin

+0

Ack ... J'aurais dû mentionner que je suis sur SQL Server 2000, pas 2005. – IronicMuffin

+0

Cela ne fonctionnera pas alors. Vous pouvez le déplacer dans les sous-requêtes de la liste 'SELECT'. – Quassnoi