2011-04-07 34 views
3

我有一個複雜的視圖,在此所說明:View of multiple tables. Need to remove "doubles" defined by 1 tableSQL Server視圖「中,選擇其中x是不是空」需要年齡完成

我用了一個Cross Apply在裏面,代碼是這樣的:(請檢查以上網址瞭解視圖)

SELECT dbo.InstellingGegevens.INST_SUBTYPE 
      , dbo.InstellingGegevens.INST_BRON 
      , dbo.InstellingGegevens.INST_INSTELLINGSNUMMER 
      , dbo.InstellingGegevens.INST_NAAM 
      , dbo.InstellingGegevens.INST_KORTENAAM 
      , dbo.InstellingGegevens.INST_VESTIGINGSNAAM 
      , dbo.InstellingGegevens.INST_ROEPNAAM 
      , dbo.InstellingGegevens.INST_STATUUT 
      , dbo.InstellingGegevens.ONDERWIJSNIVEAU_REF 
      , dbo.InstellingGegevens.ONDERWIJSSOORT_REF 
      , dbo.InstellingGegevens.DATUM_TOT 
      , dbo.InstellingGegevens.DATUM_VAN 
      , dbo.InstellingGegevens.VERBOND_REF 
      , dbo.InstellingGegevens.VSKO_LID 
      , dbo.InstellingGegevens.NET_REF 
      , dbo.Instellingen.Inst_ID 
      , dbo.Instellingen.INST_TYPE 
      , dbo.Instellingen.INST_REF 
      , dbo.Instellingen.INST_LOC_REF 
      , dbo.Instellingen.INST_LOCNR 
      , dbo.Instellingen.Opt_KalStandaard 
      , dbo.InstellingTelecom.INST_TEL 
      , dbo.InstellingTelecom.INST_FAX 
      , dbo.InstellingTelecom.INST_EMAIL 
      , dbo.InstellingTelecom.INST_WEB 
      , dbo.InstellingAdressen.SOORT 
      , dbo.InstellingAdressen.STRAAT 
      , dbo.InstellingAdressen.POSTCODE 
      , dbo.InstellingAdressen.GEMEENTE 
      , dbo.InstellingAdressen.GEM_REF 
      , dbo.InstellingAdressen.FUSIEGEM_REF 
      , dbo.InstellingAdressen.FUSIEGEM 
      , dbo.InstellingAdressen.ALFA_G 
      , dbo.InstellingAdressen.PROVINCIE 
      , dbo.InstellingAdressen.BISDOM 
      , dbo.InstellingAdressen.ARRONDISSEMENT 
      , dbo.InstellingAdressen.GEWEST 
      , dbo.InstellingContPersDirecteurs.AANSPREKING 
      , dbo.InstellingContPersDirecteurs.CONTACTPERSOON 
      , dbo.InstellingContPersDirecteurs.FUNCTIE 
      , InstellingLogin.Inst_Gebruikersnaam 
      , InstellingLogin.Inst_Concode 
      , InstellingLogin.Inst_DirCode 
      , InstellingLogin.DOSSNR 
      , InstellingLogin.Instelling_ID 
FROM dbo.InstellingGegevens 
RIGHT OUTER JOIN dbo.Instellingen 
    ON dbo.InstellingGegevens.INST_TYPE = dbo.Instellingen.INST_TYPE 
    AND dbo.InstellingGegevens.INST_REF = dbo.Instellingen.INST_REF 
    AND dbo.InstellingGegevens.INST_LOC_REF = dbo.Instellingen.INST_LOC_REF 
    AND dbo.InstellingGegevens.INST_LOCNR = dbo.Instellingen.INST_LOCNR 
LEFT OUTER JOIN dbo.InstellingTelecom 
    ON dbo.InstellingGegevens.INST_TYPE = dbo.InstellingTelecom.INST_TYPE 
    AND dbo.InstellingGegevens.INST_REF = dbo.InstellingTelecom.INST_REF 
    AND dbo.InstellingGegevens.INST_LOC_REF = dbo.InstellingTelecom.INST_LOC_REF 
LEFT OUTER JOIN dbo.InstellingAdressen 
    ON dbo.InstellingGegevens.INST_TYPE = dbo.InstellingAdressen.INST_TYPE 
    AND dbo.InstellingGegevens.INST_REF = dbo.InstellingAdressen.INST_REF 
    AND dbo.InstellingGegevens.INST_LOC_REF = dbo.InstellingAdressen.INST_LOC_REF 
LEFT OUTER JOIN dbo.InstellingContPersDirecteurs 
    ON dbo.InstellingGegevens.INST_TYPE = dbo.InstellingContPersDirecteurs.INST_TYPE 
    AND dbo.InstellingGegevens.INST_REF = dbo.InstellingContPersDirecteurs.INST_REF 
    AND dbo.InstellingGegevens.INST_LOC_REF = dbo.InstellingContPersDirecteurs.INST_LOC_REF 
CROSS APPLY 
     (SELECT TOP (1) * 
     FROM InstellingLogin AS il 
     WHERE Instellingen.INST_LOC_REF = il.Inst_Loc_REF 
      AND Instellingen.INST_LOCNR = il.Inst_Loc_Nr 
      AND Instellingen.INST_REF = il.Inst_InstellingIKON_REF 
      AND Instellingen.INST_TYPE = il.Inst_InstellingIKONType 
     ORDER BY CASE 
        WHEN il.datum_tot IS NULL 
        THEN 0 ELSE 1 
        END 
        , il.datum_tot DESC) InstellingLogin 

此視圖返回約5.5k行,大約1s。這很快!

但是!

當我把這種觀點與where子句:

SELECT * 
    FROM [Tink].[dbo].[InstellingAlleDetails] 
    where gemeente is not null and (DATUM_TOT is null or DATUM_TOT > GETDATE()) 
    order by GEMEENTE, POSTCODE,STRAAT, INST_NAAM 

需要1分20秒返回所有行。

當我放棄gemeente is not null部分時,它又需要1秒。

Gemeente是一個varchar(255)。我也試過用Inst_Naam is not null,那也花了大約1分30秒。

爲什麼is not null需要這麼多時間?更重要的是:我如何解決這個問題?

+0

'Inst_Naam'沒有出現在這個視圖中......正如HLGEM所說,你真的需要運行兩個查詢(帶/不帶'is null'條件),並比較執行計劃。如果您可以確定差異,請將其添加到您的問題中。 – 2011-04-07 13:51:41

回答

3

我不知道爲什麼。可能SQL Server提出了一個不太好的查詢計劃。

您可以嘗試首先運行沒有gemeente is not null的查詢,並將結果放入臨時表中,然後使用gemeente is not null查詢臨時表。

select * 
into #TempTable 
from YourView 

select * 
from #TempTable 
where gemeente is not null 

drop table #TempTable 
+0

所以這意味着要創建一個表,或者有一個簡單的方法來創建一個臨時表? – Stefanvds 2011-04-07 13:46:40

+0

@Stefanvds - 用一些創建臨時表的代碼更新了答案,使用它並在完成時刪除它。在1s中執行的 – 2011-04-07 13:50:14

+0

:D很好的解決方法! – Stefanvds 2011-04-07 13:52:44

1

首先檢查帶有或不帶有非空值的查詢的執行計劃,並查看差異。

順便說一句,這些連接到其他視圖的任何?這可能會導致巨大的性能問題。

+0

是的,'InstellingContPersDirecteurs'是一個視圖,但這不是我想的問題。沒有'交叉申請'它工作得很快(1s)我想它與'交叉申請'然後 – Stefanvds 2011-04-07 13:49:44

+0

我懷疑這是'CROSS APPLY'具體。有了這個複雜的查詢(幾個視圖,外部聯接,交叉應用,它們都加起來),你可能已經達到了優化器嘗試從「IS NOT NULL」謂詞獲益的嘗試導致錯誤結論的地步。將結果插入到中間表中,然後處理該中間表,這是我個人發現的防止這種情況的唯一方法。 – MatBailie 2011-04-07 14:01:33

+0

感謝您的時間! – Stefanvds 2011-04-07 14:15:20