2017-02-13 23 views
1

我有一个查询,它在下面的代码中isn时date条款“和datediff(day,con2.DT_DateIncluded),'2017-01-01')< = 0”在查询中未使用,但在包含它时运行缓慢。虽然运行速度很快,但只运行“select top 2 ID_Contact ...”部分,甚至包括date子句。我有一个经典的ASP应用程序的查询,它不能转换为存储过程(项目范围的原因)。你能通过改变查询代码来帮助我找到一种方法来提高完整查询的性能吗?带有datediff功能的慢T-SQL查询

select distinct top 10 
    ID_Contact, NO_CodCompany 
from 
    tblContacts con1 
where 
    ID_Contact in (select top 2 ID_Contact 
        from tblContacts con2 
        inner join tblCompanies cp on con2.NO_CodCompany = cp.ID_Company 
        where con2.NO_CodCompany = con1.NO_CodCompany 
        and datediff(day, con2.DT_DateIncluded), '2017-01-01') <= 0) 

回答

1

这基本上是你的查询: 这是您的查询:

select distinct top 10 ID_Contact, NO_CodCompany 
from tblContacts con1 
where ID_Contact in (select top 2 ID_Contact 
        from tblContacts con2 inner join 
          tblCompanies cp 
          on con2.NO_CodCompany = cp.ID_Company 
        where con2.NO_CodCompany = con1.NO_CodCompany and 
          datediff(day, con2.DT_DateIncluded), '2017-01-01') <= 0 
        ); 

我的第一个建议是将datediff()更改为简单日期比较:

select distinct top 10 ID_Contact, NO_CodCompany 
from tblContacts con1 
where ID_Contact in (select top 2 ID_Contact 
        from tblContacts con2 inner join 
          tblCompanies cp 
          on con2.NO_CodCompany = cp.ID_Company 
        where con2.NO_CodCompany = con1.NO_CodCompany and 
          con2.DT_DateIncluded < '2017-01-02' 
        ); 

然后,我将删除子查询中的JOIN。我不是100%肯定这是完全等价的,因为这可能取决于细微差别的数据:

select distinct top 10 ID_Contact, NO_CodCompany 
from tblContacts con1 
where con1.ID_Contact in (select top 2 con2.ID_Contact 
          from tblCompanies cp 
          where con1.NO_CodCompany = cp.ID_Company and 
           con1.DT_DateIncluded < '2017-01-02' 
         ); 

然后,如果你能在最外层查询删除select distinct,你应该做的。

+0

嗨Gordon Linoff,谢谢你的SUPER快速回复。尽管我不得不说,在这些修改建议后,它会一直运行缓慢,但我会将它们保留在代码中,因为它们可能会增加一些性能......干杯! –

+0

'DATEDIFF('2017-01-01 11:59:50','2017-01-01')'仍然有'0'的值。等价代码将是'DT_DateIncluded''20170102',而不是'DT_DateIncluded''20170101'' –

+0

@JoelCoehoorn。 。 。目前尚不清楚名为DateIncluded的字段是否会有时间分量 - 尽管如果“dt”前缀意味着暗示“datetime”,这是非常合理的。我更新了答案。 –

1

试试这个:

con2.DT_DateIncluded < '20170102' 

这是更好,因为它仍然允许服务器使用任何索引上的DT_DateIncluded列。目前,这是不可能的。更糟糕的是,查询可能不得不在表中的每条记录上运行DATEDIFF()函数。

请注意,这个等于您发布的内容,即使它可能与您的意图不符。我怀疑con2.DT_DateIncluded < '20170101'更接近你的意思。

我也怀疑你可以做到这一点,或者没有tblContacts的第二个实例或使用窗口函数来获得更好的结果,或者至少通过使用JOIN而不是IN来过滤结果。

最后,由于历史原因,输入日期,唯一的价值时,你应该在这里说明使用未分离日期格式:

The ultimate guide to the datetime datatypes

对于日期/时间值,你仍然可以使用你习惯的yyyy-mm-dd hh:mm:ss,但如果你只有日期部分,yyyymmdd更好。


基于此评论:

我的这个查询的目标是获得来自公司,但有限的接触,以“N”每家公司的联系人

你应该看看APPLY运营商。不幸的是,它仍然不是很清楚,我的一切是如何结合在一起的,但使用APPLY操作,以显示每家公司的两个触点,可以作为一个起点使用,我会至少提供一个演示:

SELECT TOP 10 ct.ID_Contact, ct.NO_CodCompany 
FROM tblCompanies cp 
CROSS APPLY (
    SELECT TOP 2 ID_Contact, NO_CodCompany 
    FROM tblContacs 
    WHERE NO_CodCompany = cp.ID_Company 
     AND DT_DateIncluded < '20170102' 
    ORDER BY DT_DateIncluded DESC 
) ct 

APPLY作品种类如嵌套的SELECT查询中的JOIN,其中没有ON子句;条件连接将作为嵌套SELECT语句中WHERE子句的一部分包含在内。

请注意使用CROSS。这将排除根本没有联系的公司。如果要包含这些公司,请将其更改为OUTER

你也应该看看你定义了哪些索引。在tblContacts表中查找NO_CodCompanyDT_DateIncluded(按此顺序!)的单个索引可能会为此查询创造奇迹,尤其是在INCLUDES子句中还有ID_Contact时。然后,您可以完全从索引完成查询的tblContacts部分。

+0

大家好,谁发布了评论。添加建议的更改后,仍然没有喜悦...我的这个查询的目标是从公司获取联系人,但限于每个公司的“n”个联系人(在我用作示例的查询中,n = 2)。我作为例子发布的查询完美地完成了这项工作,但是当我在其中添加日期子句时,它得到“不可能的缓慢”。此日期字段已被编入索引,并且我已将datediff表达式更改为简单的DT_DateIncluded> ='20170101'。但仍然没有喜悦......我会很满意与日期条款或没有它通常执行的不同查询。 –

+0

@ Claudio.hz看到我更新的答案。如果这有帮助,我会很感激听到前后的时间。 –

1

相反DATEDIFF的`()< 0' 尝试使用:

and con2.DT_DateIncluded <= '2017-01-01' 

此外,确保有在`DT_DateIncluded索引”列。

运行缓慢的原因是使用它需要一点时间来执行计算,查询优化器(可能)会结束运行它的整个表,并有(可能)没有索引来帮助它选择所需的行。

当您删除该子句时,查询运行得更快,但这可能有助于您只选择内部查询中的前两行和外部查询中的十行,从而允许表扫描足够高性能。