3

私は、毎日のコンテンツの選択を保存する場所をデータ化できます。これは日ごとに異なります。

複数の日を選択すると、すべての日で同じアイテムを返品する必要があります。

私はこのようなことを試しました:

SELECT * FROM
                        (
                             SELECT
                                ( -- For count
                                SELECT COUNT(recipeId) AS [Count]
                                FROM DailyContentDish
                                WHERE
                                    (
                                        (weekDayId=@mon OR @mon IS NULL) OR
                                        (weekDayId=@tue OR @tue IS NULL) OR
                                        (weekDayId=@wed OR @wed IS NULL) OR
                                        (weekDayId=@thu OR @thu IS NULL) OR
                                        (weekDayId=@fri OR @fri IS NULL) OR
                                        (weekDayId=@sat OR @sat IS NULL) OR
                                        (weekDayId=@sun OR @sun IS NULL) 
                                    ) 
                                    GROUP BY DailyContentDish.recipeId
                                ) AS cnt, 
                                -- End for count
                                DailyContentDish.dailyContentDishId,
                                DailyContentDish.recipeId AS Rec, 
                                title, 
                                150 AS calories, 
                                defaultSmallImagePath,
                                activePreparationTime + passivePreparationTime AS overallPreparationTime,
                                CAST(
                                    CASE WHEN EXISTS
                                        (
                                        SELECT  DailyContentDishFavourite.dailyContentDishFavouriteId
                                        FROM DailyContentDishFavourite 
                                        WHERE DailyContentDishFavourite.dailyContentDishId = DailyContentDish.dailyContentDishId
                                        )
                                    THEN 1 
                                    ELSE 0
                                END 
                                AS BIT) AS isFavouriteWhenGeneratingMenu


                                FROM DailyContentDish
                                LEFT OUTER JOIN
                                    RecipesTranslations ON RecipesTranslations.recipeId = DailyContentDish.recipeId
                                LEFT OUTER JOIN
                                    RecipeAdditionalInformation ON RecipeAdditionalInformation.recipeId = DailyContentDish.recipeId
                    WHERE
                    isEnabled = 1 AND
                    mealId=@mealId AND 
                        (       
                                weekDayId=@mon OR
                                weekDayId=@tue OR
                                weekDayId=@wed OR
                                weekDayId=@thu OR
                                weekDayId=@fri OR
                                weekDayId=@sat OR
                                weekDayId=@sun
                                )

                            ) p
                            WHERE p.cnt = @daysCount

問題は、count を返すネストされた select が、1 つのエントリ (つまり、各行) だけでなく、すべての行に対してそれを返すことです。レシピIDのエントリが複数回入力されているので、何回入力されているか知りたいです。

SELECT
                                ( -- For count
                                SELECT COUNT(recipeId) AS [Count]
                                FROM DailyContentDish
                                WHERE
                                    (
                                        (weekDayId=@mon OR @mon IS NULL) OR
                                        (weekDayId=@tue OR @tue IS NULL) OR
                                        (weekDayId=@wed OR @wed IS NULL) OR
                                        (weekDayId=@thu OR @thu IS NULL) OR
                                        (weekDayId=@fri OR @fri IS NULL) OR
                                        (weekDayId=@sat OR @sat IS NULL) OR
                                        (weekDayId=@sun OR @sun IS NULL) 
                                    )  AND Something should be here (I guess)
                                    GROUP BY DailyContentDish.recipeId
                                ) AS cnt, 
                                -- End for count

この部分は、選択した各行のエントリの COUNT を返す必要がありますが、すべてのエントリの COUNT を返します。

それとも、これで別の道を歩むべきですか。どんなヒントでも大歓迎です。

MS SQL サーバー 2008 を使用しています

編集:これはストアドプロシージャ全体です:

        @userId int,
        @languageId int,
        @mealId int,
        @mon int,
        @tue int,
        @wed int,
        @thu int,
        @fri int,
        @sat int,
        @sun int,
        @orderBy nvarchar(2),
        @pageSize int,
        @startRowIndex int

AS
BEGIN

SET NOCOUNT ON;

DECLARE @daysCount int
SET @daysCount = 0
IF (@mon IS NOT NULL)
    BEGIN
        SET @daysCount = @daysCount+1
    END
IF (@tue IS NOT NULL)
    BEGIN
        SET @daysCount = @daysCount+1
    END
IF (@wed IS NOT NULL)
    BEGIN
        SET @daysCount = @daysCount+1
    END
IF (@thu IS NOT NULL)
    BEGIN
        SET @daysCount = @daysCount+1
    END
IF (@fri IS NOT NULL)
    BEGIN
        SET @daysCount = @daysCount+1
    END
IF (@sat IS NOT NULL)
    BEGIN
        SET @daysCount = @daysCount+1
    END
IF (@sun IS NOT NULL)
    BEGIN
        SET @daysCount = @daysCount+1
    END


-- Insert statements for procedure here
    SELECT *
    FROM (
SELECT
    (
        SELECT [Count] = COUNT(recipeId) 
        FROM dbo.DailyContentDish d
        WHERE
        (
            ISNULL(@mon, weekDayId) = weekDayId OR
            ISNULL(@tue, weekDayId) = weekDayId OR
            ISNULL(@wed, weekDayId) = weekDayId OR
            ISNULL(@thu, weekDayId) = weekDayId OR
            ISNULL(@fri, weekDayId) = weekDayId OR
            ISNULL(@sat, weekDayId) = weekDayId OR
            ISNULL(@sun, weekDayId) = weekDayId 
        ) 
        GROUP BY d.recipeId
    ) AS cnt, 
    d.dailyContentDishId,
    d.recipeId AS Rec, 
    title, 
    150 AS calories, 
    defaultSmallImagePath,
    activePreparationTime + passivePreparationTime AS overallPreparationTime,
    CASE WHEN d2.dailyContentDishId IS NULL THEN 1 ELSE 0 END AS isFavouriteWhenGeneratingMenu
FROM dbo.DailyContentDish d
LEFT JOIN dbo.RecipesTranslations r ON r.recipeId = d.recipeId
LEFT JOIN dbo.RecipeAdditionalInformation t ON t.recipeId = d.recipeId
LEFT JOIN dbo.DailyContentDishFavourite d2 ON d.dailyContentDishId = d2.dailyContentDishId
WHERE isEnabled = 1 
    AND mealId = @mealId 
    AND (       
        weekDayId = @mon OR
        weekDayId = @tue OR
        weekDayId = @wed OR
        weekDayId = @thu OR
        weekDayId = @fri OR
        weekDayId = @sat OR
        weekDayId = @sun
    )
    ) p
    WHERE p.cnt = @daysCount

Edit1:図をアップロードしました: データベース図

サンプル データ (食事 ID = 1 の場合、これもフォームで選択されます) と説明: - ID 125 のレシピは、月曜日 (weekDayId = 1) と土曜日 (weekDayId = 7) に表示されます。したがって、月曜日のみを選択した場合、または土曜日のみを選択した場合、または月曜日と土曜日を選択した場合は、このレシピを返す必要があります。他の日も選択した場合、このレコードは返されません。- 曜日 1、6、および 7 (月曜日、土曜日、日曜日) が選択されている場合は、ID 105 のレシピを返す必要があります。上記と同様に、他の日が選択されている場合、このレコードは返されません。 サンプルデータ

4

4 に答える 4

1

その日と同じ食事(および食事)のみを返却する必要があります

欠けているのは、外側のクエリと内側のクエリのカウント計算との相関関係です。すなわち、次のとおりです。

( DC1.WeekDayId In( @Mon, @Tue, @Wed, @Thu, @Fri, @Sat, @Sun )
    Or Coalesce( @Mon, @Tue, @Wed, @Thu, @Fri, @Sat, @Sun ) Is Null )
And DC1.MealId = DC.MealId

これを実現するには、少なくとも 1 つのテーブルにエイリアスを設定する必要があります。通常、内部クエリと外部クエリの両方でテーブルにエイリアスを設定すると、読みやすくなります。欠けているもう 1 つの項目は、各日の 7 つの変数が、その日自体ではなくティック (「この日を選択」) を表していることです。これを変更すると、クエリがより簡単になります。

Select @Mon = Case When @Mon Is Not Null Then 1 End
    , @Tue = Case When @Tue Is Not Null Then 2 End
    , @Wed = Case When @Wed Is Not Null Then 3 End
    , @Thu = Case When @Thu Is Not Null Then 4 End
    , @Fri = Case When @Fri Is Not Null Then 5 End
    , @Sat = Case When @Sat Is Not Null Then 6 End
    , @Sun = Case When @Sun Is Not Null Then 7 End;

 Select Count(*) Over() As CountOfResults
    ,   (
        Select Count(*)
        From DailyContentDish As DC1
        Where DC1.weekDayId = DC.weekDayId
        ) As CountOfDishesOnDay
    ,   (
        Select Count(Distinct mealId)
        From DailyContentDish As DC1
        Where DC1.weekDayId = DC.weekDayId
        ) As CountOfMeals           
    , DC.DailyContentDishId
    , DC.RecipeId As Rec
    , Title
    , 150 As Calories
    , DefaultsMallImagePath
    , ActivePreparationTime 
        + PassivePreparationTime As OverallPreparationTime
    , Cast  (
            Case 
            When Exists (
                        Select 1
                        From DailyContentDishFavourite As DF1
                        Where DF1.DailyContentDishId = DC.DailyContentDishId
                        ) Then 1 
            Else 0
            End 
            As Bit) As IsFavouriteWhenGeneratingMenu
From DailyContentDish As DC
    Left Join RecipesTranslations As RT
        On RT.RecipeId = DC.RecipeId
    Left Join RecipeAdditionalInformation As RA
        On RA.RecipeId = DC.RecipeId
Where DC.IsEnabled = 1 
    And DC.MealId=@MealId 
    And DC.WeekDayId In( @Mon, @Tue, @Wed, @Thu, @Fri, @Sat, @Sun )

添加

日次変数が 1 日あたりに返される結果の数を表すと想定されている場合 (たとえば、 の場合@Mon = 2、月曜日に 2 行を返す必要があります)、次のようにすることができます。

Declare @DailyParameters Table
    (
    DayCount int not null
    , DayOfWeek int not null
    )

Insert @DailyParameters( DayCount, DayOfWeek )
Select Z.Cnt, Z.DayOfWeek
From    (
        Select @Mon As Cnt, 1 As DayOfWeek
        Union All Select @Tue, 2
        Union All Select @Wed, 3
        Union All Select @Thu, 4
        Union All Select @Fri, 5
        Union All Select @Sat, 6
        Union All Select @Sun, 7
        ) As Z
Where Z.Cnt Is Not Null

Where 句は次のように変更されます。

Where DC.IsEnabled = 1 
    And DC.MealId = @MealId 
    And DC.WeekDayId In( Select DayOfWeek From @DailyParameters )
    And (
        Select Count(*)
        From DailyContentDish As DC1
        Where DC1.weekDayId = DC.weekDayId
        ) = (
            Select D1.DayCount
            From @DailyParameters As D1
            Where D1.DayOfWeek = DC.weekDayId
            )
于 2013-05-17T16:24:30.227 に答える
0

"レシピ ID のエントリが複数回入力されているため、何回入力されているか知りたいです。 "

このステートメントに基づいて、COUNT で OVER 句を使用します。

何かのようなもの:

SELECT
  COUNT(*) OVER (PARTITION BY recipeId) AS 'cnt'
  FROM DailyContentDish

詳細を提供するために、テーブルと出力がどうあるべきかについての詳細が必要です。

2008 年の OVER 句の詳細は次のとおりです。 http://msdn.microsoft.com/en-us/library/ms189461(v=sql.105).aspx

OVER で COUNT を使用する例: http://blog.sqlauthority.com/2011/08/11/sql-server-tips-from-the-sql-joes-2-pros-development-series-advanced-aggregates-with- the-over-clause-day-11-of-35/

于 2013-05-17T13:06:51.893 に答える