2009-10-03 8 views
0

J'ai 3 tables Site, Prix et PrixMonth. Le site a beaucoup de prix (joint sur siteId). PriceMonth contient une date qui est recherchée par Price (rejoint sur PriceMonth). L'idée est que les enregistrements de prix sont créés lorsqu'un site est créé comme espace réservé.SQL Update - Existe-t-il un moyen plus élégant et plus efficace de le faire?

Lorsqu'un utilisateur clique sur une ligne de prix dans une vue - je dois mettre à jour les prix pour le reste de l'année seulement et à partir de ce mois seulement.

J'ai écrit du code pour une procédure stockée qui fonctionne. Veuillez ignorer les valeurs codées en dur pour le moment. Cela fonctionne mais peut-il être rendu plus simple et plus efficace?

code:

DECLARE @startDate smallDateTime     
DECLARE @roc decimal(5,2) 
DECLARE @Lec decimal(5,2) 
DECLARE @power decimal(5,2) 

SET @roc = (SELECT roc FROM [Price] WHERE siteId = 77 AND PriceMonthId = 527) 
SET @lec = (SELECT lec FROM [Price] WHERE siteId = 77 AND PriceMonthId = 527) 
SET @power = (SELECT [power] FROM [Price] WHERE siteId = 77 AND PriceMonthId = 527) 
SET @startDate = (Select [month] FROM [PriceMonth] WHERE PriceMonthId = 527) 

UPDATE 
    Price 
SET 
    roc = @roc 
, lec = @lec 
, [power] = @power 
FROM 
    Price 
    INNER JOIN priceMonth pm ON price.priceMonthId = pm.priceMonthId 

WHERE 
    (DATEPART(mm,pm.[Month]) > DATEPART(mm,@startDate) AND 
    (DATEPART(yy,pm.[Month]) = DATEPART(yy,@startDate))) AND 
    price.SiteId = 77 
+0

Pouvez-vous expliquer pourquoi vous avez besoin des espaces réservés? Pourquoi ne pas simplement insérer les prix lorsque vous avez les données réelles? – JohnFx

+0

Bien sûr, c'est une exigence de l'entreprise afin qu'ils n'ont pas à tous les prix d'année en année. J'ai demandé à changer cela mais je ne suis pas autorisé - donc en un mot, ça n'a pas vraiment d'importance - j'en ai besoin. – Davy

Répondre

0

Vous pouvez utiliser l'affectation multiple pour définir plusieurs variables avec les résultats d'une requête.

SELECT top 1 
    @roc = roc, 
    @lec = lec, 
    @power = power 
FROM Price 
WHERE siteId = 77 and pricemonthid = 527 

Rights Watch avec cette technique:

  • si aucune lignes sont renvoyées, les variables demeurent inchangées (null dans ce cas).
  • Si plusieurs lignes sont renvoyées, chaque ligne est affectée, ce qui laisse le dernier ensemble de valeurs comme valeurs finales. Si aucune commande n'a été spécifiée, le serveur sql détermine l'ordre des lignes et n'importe quelle ligne peut être la dernière.

Vous pouvez pré-calculer la plage de dates que vous souhaitez mettre à jour. Cela pourrait permettre à un index sur les dates d'être utile.

DECLARE @StartRange datetime, @EndRange datetime 

SET @StartRange = DateAdd(mm, DateDiff(mm, @startDate, 0), 0) 
SET @EndRange = DateAdd(yy, 1 + DateDiff(yy, @StartRange, 0), 0) 

UPDATE... 
WHERE @StartRange <= pm.Month AND pm.Month < @EndRange 
    AND price.SiteId = 77 
+0

Merci - cela semble bon.La performance dans l'application particulière n'est pas un problème mais c'est une technique utile. – Davy

1

Vous pouvez ajouter les variables comme joint à la requête comme suit:

UPDATE  p 
SET   roc = sourcePrice.roc, 
      lec = sourcePrice.lec, 
      [power] = sourcePrice.[power] 
FROM  Price p 
      INNER JOIN [Price] sourcePrice 
      on p.siteId = sourcePrice.siteId 
      and sourcePrice.siteId = 527 
      INNER JOIN priceMonth pm 
      ON price.priceMonthId = pm.priceMonthId 
      INNER JOIN priceMonth sourcepm 
      ON sourcepm.PriceMonthId = 527 

WHERE pm.[Month] > sourcepm.StartDate 
AND  (DATEPART(yy,pm.[Month]) = DATEPART(yy,sourcepm.StartDate))) 
AND  price.SiteId = 77 

Notez également que j'ai supprimé la fonction d'un de vos comparaisons de date - c'est SQL Server peut donc utiliser n'importe quel index qui pourrait être défini pour réduire au minimum la plage de valeurs.

+0

Merci Joon - J'obtiens les erreurs suivantes: Msg 4104, niveau 16, état 1, ligne 1 L'identificateur en plusieurs parties "price.priceMonthId" n'a pas pu être lié. Msg 207, niveau 16, état 1, ligne 14 Nom de colonne invalide 'StartDate'. Msg 207, niveau 16, état 1, ligne 15 Nom de colonne invalide 'StartDate'. Msg 4104, niveau 16, état 1, ligne 15 L'identificateur en plusieurs parties "price.SiteId" n'a pas pu être lié. – Davy

0

En ce qui concerne l'exigence de caractères génériques, vous pouvez toujours utiliser un LEFT JOIN et confluer pour être en mesure de se replier au prix du mois précédent. Vous pouvez également planifier une tâche pour créer les prix du nouveau mois à partir du mois précédent à minuit le dernier jour de chaque mois.

Questions connexes