sql - DateAdd 查询需要很长时间才能执行

标签 sql sql-server tsql ssms

下面的查询在 WHERE 子句上有 DateAdd

SELECT d.INVOICE_NO, d.part_no, d.PART_ORDER_QTY, d.PART_SHIPPED_QTY, d.INV_ALLOC_ORIG_DOC, d.INV_ALLOC_BR_QTY_HIST, d.INV_ALLOC_QTY_HIST, pc.PopCode, pm.SOURCE_CODE, d.BSIT_STORE, I.CUST_NO, C.Sales_type
  FROM [BSIT_ERA_RAW_DATA].[dbo].[INVOICE_ERA_LINE_DTLS] D
  LEFT JOIN [BSIT_ERA_RAW_DATA].[dbo].[INVOICE] I ON D.INVOICE_NO = I.INVOICE_NO
  LEFT JOIN [BSIT_ERA_RAW_DATA].[dbo].[PROD_MASTER] PM ON D.PART_NO = PM.PARTS_MASTER_KEY AND PM.BSIT_STORE = 'STORE01'
  LEFT JOIN [MICQIF_PROD].[dbo].[PopCodes] PC ON right(d.PART_NO,len(d.part_no)-2) COLLATE SQL_Latin1_General_CP1_CI_AS = PC.ItemNo COLLATE SQL_Latin1_General_CP1_CI_AS
  LEFT JOIN [BSIT_ERA_RAW_DATA].[dbo].[CUSTOMER] C ON I.CUST_NO = C.CUSTOMER_ID AND C.BSIT_STORE = 'STORE01'
  WHERE D.PART_ISSUE_DATE >= CONVERT(DATE,DATEADD(mm, DATEDIFF(mm, 0, GETDATE()) - 1 , 0))
  AND D.PART_ISSUE_DATE <= CONVERT(varchar(10), DATEADD(mm, DATEDIFF(mm, 0, GETDATE()) , -1), 120)
  AND I.INVOICE_CLOSED_DATE <= CONVERT(varchar(10), DATEADD(mm, DATEDIFF(mm, 0, GETDATE()) , -1), 120)

  AND D.INV_ALLOC_ORIG_DOC IS NULL
  AND D.INVOICE_NO NOT LIKE 'CM%'
  AND D.PART_NO IS NOT NULL
  and d.part_no like 'cp%'
  and INVOICE_VOID_DATE IS NULL
  AND I.CUST_NO NOT IN ('90102','90103','90104','90105','90201','90203','90204','90205','90401','90402','90403','90405','90501','90502','90503','90504','90301','90302','90304','90305')

这个运行了很长时间,最终我无法完成该过程。

但是,如果将日期更改为静态日期,例如

CONVERT(DATE,DATEADD(mm, DATEDIFF(mm, 0, GETDATE()) - 1 , 0))

进入'2018-01-01'

CONVERT(varchar(10), DATEADD(mm, DATEDIFF(mm, 0, GETDATE()) , -1), 120)

输入'2018-01-31',查询将顺利运行。

谁能告诉我可能是什么问题吗?

干杯

最佳答案

摘自一篇名为 Avoid Using Functions in WHERE clause 的文章如下:

There are two reasons why you want to avoid having a function call in your WHERE clause and more specifically on the columns you are filtering on in your WHERE clause. [...The] function needs to be called for every record in the result set which can slow down your query performance. The second reason which can have even more impact on query performance is the fact that if there is a function surrounding the column you are trying to filter on, any indexes on that column can not be used.

这归结为您的函数被计算了 n 次(其中 n 是正在考虑的记录数)。您可以通过将计算的日期分配给变量,然后在 where 子句中使用该变量,将计算次数减少到 1。结果查询将如下所示:

declare @part_issue_date_min date = CONVERT(DATE,DATEADD(mm, DATEDIFF(mm, 0, GETDATE()) - 1 , 0))
    , @part_issue_date_max date = CONVERT(varchar(10), DATEADD(mm, DATEDIFF(mm, 0, GETDATE()) , -1), 120)
    , @invoice_closed_date date = CONVERT(varchar(10), DATEADD(mm, DATEDIFF(mm, 0, GETDATE()) , -1), 120)

SELECT d.INVOICE_NO, d.part_no, d.PART_ORDER_QTY, d.PART_SHIPPED_QTY, d.INV_ALLOC_ORIG_DOC, d.INV_ALLOC_BR_QTY_HIST, d.INV_ALLOC_QTY_HIST, pc.PopCode, pm.SOURCE_CODE, d.BSIT_STORE, I.CUST_NO, C.Sales_type
  FROM [BSIT_ERA_RAW_DATA].[dbo].[INVOICE_ERA_LINE_DTLS] D
  LEFT JOIN [BSIT_ERA_RAW_DATA].[dbo].[INVOICE] I ON D.INVOICE_NO = I.INVOICE_NO
  LEFT JOIN [BSIT_ERA_RAW_DATA].[dbo].[PROD_MASTER] PM ON D.PART_NO = PM.PARTS_MASTER_KEY AND PM.BSIT_STORE = 'STORE01'
  LEFT JOIN [MICQIF_PROD].[dbo].[PopCodes] PC ON right(d.PART_NO,len(d.part_no)-2) COLLATE SQL_Latin1_General_CP1_CI_AS = PC.ItemNo COLLATE SQL_Latin1_General_CP1_CI_AS
  LEFT JOIN [BSIT_ERA_RAW_DATA].[dbo].[CUSTOMER] C ON I.CUST_NO = C.CUSTOMER_ID AND C.BSIT_STORE = 'STORE01'
  WHERE D.PART_ISSUE_DATE >= @part_issue_date_min
  AND D.PART_ISSUE_DATE <= @part_issue_date_max
  AND I.INVOICE_CLOSED_DATE <= @invoice_closed_date

  AND D.INV_ALLOC_ORIG_DOC IS NULL
  AND D.INVOICE_NO NOT LIKE 'CM%'
  AND D.PART_NO IS NOT NULL
  and d.part_no like 'cp%'
  and INVOICE_VOID_DATE IS NULL
  AND I.CUST_NO NOT IN ('90102','90103','90104','90105','90201','90203','90204','90205','90401','90402','90403','90405','90501','90502','90503','90504','90301','90302','90304','90305')

关于sql - DateAdd 查询需要很长时间才能执行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48779760/

相关文章:

c++ - 在 C++ Builder 中更新 TDBGrid

python - SQLAlchemy:加入没有 from 字段的子查询

sql - 在 t-sql 中验证日期?

sql - 一个查询中的两个计数与相反的 where 条件

mysql - 保存查询结果以在 IN 比较中使用

sql-server - 序号从设定值开始

mysql - 合并来自 MySQL 存储过程的结果

sql - TSQL,如何避免 if 条件?

c# - 如何将 ASP.NET 项目拆分为具有不同模块的不同版本

sql - 将 SQL 中的 2 个表与一些不同的列名组合 (Transact SQL)