下面的查询在 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/