DateAdd Query需要很长时间才能执行

时间:2018-02-14 04:38:09

标签: sql sql-server tsql ssms

我在下面查询DateAdd子句

上有WHERE
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',查询将顺利运行。

有人可以告知可能出现什么问题吗?

干杯

1 个答案:

答案 0 :(得分:3)

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

  

有两个原因可以避免让函数调用   您的WHERE子句,更具体地说,是您的列   在WHERE子句中过滤。需要为每个记录调用[...]函数   结果集可能会降低查询性能。第二   可以对查询性能产生更大影响的原因是   事实上,如果你正在尝试的列周围有一个功能   要过滤,该列上的任何索引都不能使用。

归结为您的函数正在计算n次(其中n是要考虑的记录数)。通过将计算的日期分配给变量,可以将计算次数减少到1,然后在where子句中使用该变量。生成的查询看起来像这样:

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')