MSSQL WHERE YEAR 子句返回所有日期而不是指定日期[关闭]

Posted

技术标签:

【中文标题】MSSQL WHERE YEAR 子句返回所有日期而不是指定日期[关闭]【英文标题】:MSSQL WHERE YEAR clause returning all dates instead of date specified [closed] 【发布时间】:2020-12-11 10:49:29 【问题描述】:

这里没有人帮助我,但互联网的空白和我的谷歌搜索技能充其量是平庸的。

下面的语法返回我需要的信息,但是它给了我表中的所有日期并忽略了 WHERE 子句。我正在尝试加入 3 个表:“ProductHistory”是主要表,“Product”需要一列,第三个表“MainJobDetails”需要一个日期字段。

SELECT [ProductHistory].[Type]
    ,[ProductHistory].[Ref]
    ,[ProductHistory].[JobNo]
    ,[ProductHistory].[Quantity]
    ,[ProductHistory].[PurchasePrice]
    ,[ProductHistory].[UnitPrice]
    ,[ProductHistory].[UnitDesc]
    ,[ProductHistory].[ProductID]
    ,[ProductHistory].[Location]
    ,[ProductHistory].[UserID]
    ,[Product].[Description]
    ,[Product].[StkRef1]
    ,[MainJobDetails].[DespatchDate]
FROM [ProductHistory]
JOIN [Product] ON [ProductHistory].[ProductID] = [Product].[ID]
JOIN [MainJobDetails] ON [ProductHistory].[JobNo] = [MainJobDetails].[JobNo]
WHERE YEAR([MainJobDetails].[DespatchDate]) = 2020
AND MONTH([MainJobDetails].[DespatchDate]) = 11
AND [ProductHistory].[Type] = 5
OR [ProductHistory].[Type] = 6
ORDER BY [MainJobDetails].[DespatchDate] DESC

我尝试将 WHERE 子句更改为:

WHERE [MainJobDetails].[DespatchDate] BETWEEN '2020/10/31' AND '2020/11/30'

但这并没有什么不同。

这是我之前使用过的另一个类似查询,它运行良好:

SELECT [MainJobDetails].[JobNo]
      ,[MainJobDetails].[EstimateHeaderRef]
      ,[MainJobDetails].[InvoiceCustomerName]
      ,[MainJobDetails].[JobDesc]
      ,[MainJobDetails].[DespatchDate]
      ,[FinishingInput].[Code]
      ,[FinishingInput].[Description]
      ,[FinishingInput].[Runs]
      ,[FinishingInput].[Timedb] 
  FROM [MainJobDetails]
  LEFT JOIN [FinishingInput]
  ON [MainJobDetails].[EstimateHeaderRef]=[FinishingInput].[EstimateHeaderRef]
  WHERE [MainJobDetails].[DespatchDate] BETWEEN '2020/11/01' AND '2020/12/31'
  ORDER BY [MainJobDetails].[DespatchDate] DESC

我在第一个语句中哪里错了?

非常感谢您的帮助。

【问题讨论】:

为什么要使用MONTHYEAR?使用正确的日期逻辑:Yourdate >= '20200501' AND YourDate < '20200601'。由于查询将是 SARGable,因此性能要好得多。 当您在不使用括号的情况下混合ANDOR 时,您必须检查优先规则以确定它们如何组合。我建议您插入适当的括号,以明确其他条件在 Type 为 6 时也适用。 【参考方案1】:

OR 条件放在括号内:

WHERE 
    YEAR([MainJobDetails].[DespatchDate]) = 2020
    AND MONTH([MainJobDetails].[DespatchDate]) = 11
    AND ([ProductHistory].[Type] = 5 OR [ProductHistory].[Type] = 6)
      --^-- here                                        and here --^-- 

为什么需要它是因为OR 在逻辑表达式中的优先级低于AND。所以你的原始代码(不带括号)相当于:

WHERE 
    (
        YEAR([MainJobDetails].[DespatchDate]) = 2020
        AND MONTH([MainJobDetails].[DespatchDate]) = 11
        AND ([ProductHistory].[Type] = 5
    )
    OR [ProductHistory].[Type] = 6

您可以看到,这允许任何具有 Type 6 的产品,而不管其他条件如何。

我还建议进一步优化:

在日期上使用直接过滤而不是应用日期函数而不是存储值 - 这要高效得多

使用IN 代替ORed 条件

所以:

WHERE 
        [MainJobDetails].[DespatchDate] >= '20201101'
    AND [MainJobDetails].[DespatchDate] <  '20201201'
    AND [ProductHistory].[Type] IN (5, 6)

【讨论】:

啊!当然,我没有使用 >= 这成功了!并且数据加载速度更快。非常感谢。如果没有这个论坛,我不知道我会做什么。

以上是关于MSSQL WHERE YEAR 子句返回所有日期而不是指定日期[关闭]的主要内容,如果未能解决你的问题,请参考以下文章

联合所有 where 日期子句

无法使用 pypyodbc 在 python 中使用 where 子句运行 mssql 选择查询

MSSQL - 在 where 和 on 子句性能上添加条件

MySQL 中基于 MSSQL 语法按 YEAR 选择日期范围的等效语法是啥?

SQL 无法让 WHERE EXISTS 子句正常工作,并且仅返回在特定日期内具有客户端类型的行

Oracle:有效地使用where子句过滤时间戳列以获取特定日期的所有记录