2010-05-17 10 views
0

J'ai une base de données qui a deux tables. Ces deux tableaux sont définis comme:SQL Server 2008 - Plage conditionnelle

Movie 
----- 
ID (int) 
Title (nvchar) 

MovieReview 
----------- 
ID (int) 
MovieID (int) 
StoryRating (decimal) 
HumorRating (decimal) 
ActingRating (decimal) 

J'ai une procédure stockée qui permet à l'utilisateur d'interroger les films en fonction des critiques d'autres utilisateurs. À l'heure actuelle, j'ai une table temporaire qui est rempli avec la requête suivante:

SELECT 
    m.*, 
    (SELECT COUNT(ID) FROM MovieReivew r WHERE r.MovieID=m.ID) as 'TotalReviews', 
    (SELECT AVG((r.StoryRating + r.HumorRating + r.ActingRating)/3) 
     FROM MovieReview r WHERE r.MovieID=m.ID) as 'AverageRating' 
FROM 
    Movie m 

Dans une requête plus tard dans ma procédure, je veux essentiellement dire:

SELECT 
    * 
FROM 
    MyTempTable t 
WHERE 
    t.AverageRating >= @lowestRating AND 
    t.AverageRating <= @highestRating 

Mon problème est, parfois AverageRating est zéro. Pour cette raison, je ne sais pas quoi faire. Comment gérer ce scénario en SQL?

+1

ce que vous voulez faire quand AverageRating est égal à zéro? – eKek0

Répondre

0

Je suppose que vous voulez des films avec zéro avis inclus dans votre résultat. Il est sûr de tester TotalReviews, car il ne sera jamais NULL.

+0

doh! J'oubliais la partie OR. Merci! – user208662

+0

De rien! – egrunin

1

D'abord, j'avais utilisé une table dérivée pour calculer les statistiques. Cela rend plus facile de convertir les zéros à zéro si vous voulez (bien que si nous utilisons une jointure interne comme je suis ici, vous ne pourriez pas avoir besoin d'utiliser Coalesce sur TotalReviews).

Select m.* 
    , Coalesce(MovieStats.TotalReviews, 0) As TotalReviews 
    , Coalesce(MovieStats.AverageRating, 0) As AverageRating 
From Movie As m 
    Join (
       Select R1.MovieId 
        , Count(*) As TotalReviews 
        , AVG((r.StoryRating + r.HumorRating + r.ActingRating)/3) As AverageRating 
       From MovieReview As r1 
       Group By R1.MovieId 
       ) As MovieStats 
     On MovieStats.MovieId = m.Id 
Where MovieStats.AverageRating Between @LowestRating And @HighestRating 

Le seul problème est ici que, en mettant notre filtre dans la clause Where, cela signifie que nous devons avoir des enregistrements de MovieReview avec des valeurs AverageRating dans plage donnée.

Select m.* 
    , Coalesce(MovieStats.TotalReviews, 0) As TotalReviews 
    , Coalesce(MovieStats.AverageRating, 0) As AverageRating 
From Movie As m 
    Left Join (
       Select R1.MovieId 
        , Count(*) As TotalReviews 
        , AVG((r.StoryRating + r.HumorRating + r.ActingRating)/3) As AverageRating 
       From MovieReview As r1 
       Group By R1.MovieId 
       ) As MovieStats 
      On MovieStats.MovieId = m.Id 
       And MovieStats.AverageRating Between @LowestRating And @HighestRating 

Cela renverra zéro dans les cas où il n'y a pas le classement des films ou des cotes de films qui existent sont en dehors de la plage passé.

Une autre possibilité est de filtrer sur des valeurs qui ont des critiques et de force les avoir notes moyennes dans la gamme passé:

Select m.* 
    , Coalesce(MovieStats.TotalReviews, 0) As TotalReviews 
    , Coalesce(MovieStats.AverageRating, 0) As AverageRating 
From Movie As m 
    Left Join (
       Select R1.MovieId 
        , Count(*) As TotalReviews 
        , AVG((r.StoryRating + r.HumorRating + r.ActingRating)/3) As AverageRating 
       From MovieReview As r1 
       Group By R1.MovieId 
       ) As MovieStats 
      On MovieStats.MovieId = m.Id 
Where MovieStats.MovieId Is Null 
    Or (MovieStats.AverageRating Between @LowestRating And @HighestRating) 
+0

+1: Vous étiez le premier –