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 的嵌套选择会为所有行返回它,而不仅仅是一个条目(即每一行)。由于带有 recipeId 的条目输入的次数更多,因此我想知道它们输入了多少次。

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)出现。所以,如果我只选择星期一或者如果我只选择星期六或者如果我选择星期一和星期六,则必须返回这个食谱。如果我还选择了其他任何一天,则不会返回 ithis 记录。- 选择第 1、6 和 7 周(周一、周六、周日)时,必须返回 ID 为 105 的食谱。同上,如果选择了其他任何一天,则不返回该记录。 样本数据

4

4 回答 4

2
SELECT *
FROM (
      SELECT
        ( -- For count
         SELECT COUNT(d.recipeId) AS [Count]
         FROM DailyContentDish d
         WHERE (
                ISNULL(@amon, d.weekDayId) = d.weekDayId OR
                ISNULL(@tue, d.weekDayId) = d.weekDayId OR
                ISNULL(@wed, d.weekDayId) = d.weekDayId OR
                ISNULL(@thu, d.weekDayId) = d.weekDayId OR
                ISNULL(@fri, d.weekDayId) = d.weekDayId OR
                ISNULL(@sat, d.weekDayId) = d.weekDayId OR
                ISNULL(@sun, d.weekDayId) = d.weekDayId 
                ) AND d.recipeId = DailyContentDish.recipeId
          GROUP BY d.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

更新 21.05.2013(添加演示)

IF OBJECT_ID('tempdb.dbo.#weekDays') IS NOT NULL DROP TABLE dbo.#weekDays     
SELECT weekDayId
INTO dbo.#weekDays
FROM(VALUES(@mon),
           (@tue),
           (@wed),
           (@thu),
           (@fri),
           (@sat),
           (@sun))x(weekDayId)
WHERE weekDayId IS NOT NULL

CREATE UNIQUE CLUSTERED INDEX x ON dbo.#weekDays(weekDayId)

SELECT d.dailyContentDishId,
       d.recipeId AS Rec, 
       title, 
       150 AS calories, 
       defaultSmallImagePath,
       activePreparationTime + passivePreparationTime AS overallPreparationTime,
       CASE WHEN f.dailyContentDishId IS NULL THEN 1 ELSE 0 END AS isFavouriteWhenGeneratingMen
FROM DailyContentDish d
  LEFT JOIN RecipesTranslations ON RecipesTranslations.recipeId = d.recipeId
  LEFT JOIN RecipeAdditionalInformation ON RecipeAdditionalInformation.recipeId = d.recipeId
  LEFT JOIN dbo.DailyContentDishFavourite f ON d.dailyContentDishId = f.dailyContentDishId
WHERE d.isEnabled = 1 AND d.mealId = @mealId 
  AND NOT EXISTS(          
                 SELECT d3.weekDayId
                 FROM dbo.#weekDays d3
                 EXCEPT
                 SELECT d2.WeekDayId
                 FROM DailyContentDish d2
                 WHERE d.recipeId = d2.recipeId 
                   AND d2.isEnabled = 1 AND d2.mealId = @mealId 
                 )

SQLFiddle上的简单演示

于 2013-05-17T13:21:44.443 回答
2

这可能会帮助你 -

ALTER PROCEDURE dbo.usp_GetDailyContentDish

    @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
    SELECT @daysCount = 
        CASE WHEN @mon IS NOT NULL THEN 1 ELSE 0 END +
        CASE WHEN @tue IS NOT NULL THEN 1 ELSE 0 END +
        CASE WHEN @wed IS NOT NULL THEN 1 ELSE 0 END +
        CASE WHEN @thu IS NOT NULL THEN 1 ELSE 0 END +
        CASE WHEN @fri IS NOT NULL THEN 1 ELSE 0 END +
        CASE WHEN @sat IS NOT NULL THEN 1 ELSE 0 END + 
        CASE WHEN @sun IS NOT NULL THEN 1 ELSE 0 END 

    SELECT
          Rec
        , calories
        , overallPreparationTime
        , isFavouriteWhenGeneratingMenu
    FROM (
        SELECT
            (
                SELECT [Count] = COUNT(d3.recipeId) 
                FROM dbo.DailyContentDish d3
                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 
                ) AND d3.recipeId = d.recipeId 
                GROUP BY d3.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

END

小型机顶盒:

这个:

AND (       
    weekDayId = @mon OR
    weekDayId = @tue OR
    weekDayId = @wed OR
    weekDayId = @thu OR
    weekDayId = @fri OR
    weekDayId = @sat OR
    weekDayId = @sun
)

可能对此进行优化:

weekDayId % @weekDay = 0

如果@mon,@tue不为空且包含 1、2、...

于 2013-05-17T12:35:48.037 回答
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

您需要为至少其中一个表设置别名才能实现此目的。通常,如果您在内部和外部查询中为表设置别名,则更容易阅读。缺少的另一项是每天的七个变量代表刻度(“选择这一天”)而不是当天本身。如果我们改变它,它会使查询更简单。

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 )

添加

如果每日变量应该代表每天返回的结果计数(例如,如果@Mon = 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

"由于带有 recipeId 的条目输入的次数超过一次,我想知道它们输入了多少次。 "

基于此语句,我将只使用带有 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

使用 COUNT 和 OVER 的示例:http: //blog.sqlauthority.com/2011/08/11/sql-server-tips-from-the-sql-joes-2-pros-development-series-advanced-aggregates-with- 35 日第 11 天/

于 2013-05-17T13:06:51.893 回答