2017-02-13 24 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索引」列。

運行緩慢的原因是使用它需要一點時間來執行計算,查詢優化器(可能)會結束運行它的整個表,並有(可能)沒有索引來幫助它選擇所需的行。

當您刪除該子句時,查詢運行得更快,但這可能有助於您只選擇內部查詢中的前兩行和外部查詢中的十行,從而允許表掃描足夠高性能。