2012-05-21 31 views
1

以下是內聯表值函數如何在表值函數中使用條件聯合ALL?

CREATE FUNCTION [dbo].[GetDipForDirectClientCharts] 
(
    @FacilityId AS UNIQUEIDENTIFIER , 
    @PatientChartStatusCompleteEnum SMALLINT , 
    @PatientChartLockingInterval SMALLINT 
) 
RETURNS TABLE 
AS RETURN 
(   
    WITH DirectPatientChartCTE 
       --Get all patient charts that qualify for dip criteria 
       AS (SELECT TOP 500 
          VisitNumber,PatientChartID 
        FROM  PatientChartCorporate WITH (READPAST) 
        WHERE PatientChartCorporate.IsDeleted = 0 
          AND PatientChartCorporate.IsErroneous = 0 
          AND PatientChartCorporate.FacilityId = @FacilityId 
          AND (DipFileName IS NULL 
            OR DipFileName = '' 
           ) 
          AND PatientChartCorporate.ChartStatusID = @PatientChartStatusCompleteEnum 
          AND DATEDIFF(MINUTE, CompletedOn, GETUTCDATE()) >= +CONVERT(VARCHAR(30), @PatientChartLockingInterval) 
          AND (PatientChartCorporate.CompletedOn IS NOT NULL) 
       ), 
      RemotePatientChartCTE 
       AS (SELECT TOP 500 
          VisitNumber,PatientChartID 
        FROM  PatientCharts WITH (READPAST) 
        WHERE PatientCharts.IsDeleted = 0 
          AND PatientCharts.IsErroneous = 0 
          AND PatientCharts.FacilityId = @FacilityId 
          AND (DipFileName IS NULL 
            OR DipFileName = '' 
           ) 
          AND PatientCharts.ChartStatusID = @PatientChartStatusCompleteEnum 
          AND DATEDIFF(MINUTE, CompletedOn, GETUTCDATE()) >= +CONVERT(VARCHAR(30), @PatientChartLockingInterval) 
          AND (PatientCharts.CompletedOn IS NOT NULL) 
       ) 
SELECT PatientCharts.VisitNumber , 
     PatientChartImages.ImageSequence AS ImageSequence 
FROM dbo.PatientChartImagesCorporate AS PatientChartImages WITH (READPAST) 
     INNER JOIN DirectPatientChartCTE AS PatientCharts ON PatientChartImages.PatientChartId = PatientCharts.PatientChartId 
WHERE Patientchartimages.OnbasedDate IS NULL 
UNION ALL 
(SELECT PatientCharts.VisitNumber , 
      PatientChartImages.ImageSequence AS ImageSequence 
    FROM  dbo.PatientChartImages AS PatientChartImages WITH (READPAST) 
      INNER JOIN RemotePatientChartCTE AS PatientCharts ON PatientChartImages.PatientChartId = PatientCharts.PatientChartId 
    WHERE  Patientchartimages.OnbasedDate IS NULL 
) 
    ) 

我定義了兩個CTE,DirectPatientChartCTERemotePatientChartCTE。如果0記錄由RemotePatientChartCTE返回,我不想使用union。

據我所知,我可以在查詢下使用union子語中的where子句來檢查CTE中的0條記錄。在這種情況下,第二個查詢也會被評估。如果記錄不存在,我不希望第二個查詢中的表進行掃描。

這已經從一個視圖更改爲內聯TVF,因爲視圖的性能很糟糕。我不能使用SP,因爲我必須用這個TVF的結果填充動態臨時表。請建議。

+1

當查詢中的其中一個表要返回0行,並且INNER JOIN連接到查詢中的其他表時,則應該發生其他表的「實際」掃描,假設優化器可以很好地完成工作,並且索引是合適的。生成0結果通常是一種快速操作。 –

回答

2

你可以把你的函數變成一個多語句表值函數。一次執行CTE中的查詢,並將每個查詢的結果存儲在表變量中。然後,您可以檢查第二個表變量中的行數,並在必要時執行聯合查詢。

在僞代碼這樣的東西。

declare @Direct table 
(
    PatientChartID int primary key, 
    VisitNumber int 
) 

declare @Remote table 
(
    PatientChartID int primary key, 
    VisitNumber int 
) 

insert into @Direct 
select top 500 VisitNumber,PatientChartID 
from PatientChartCorporate 
--where .... 

insert into @Remote 
select top 500 VisitNumber,PatientChartID 
from PatientChartCorporate 
--where .... 

if exists(select * from @Remote) 
begin 
    -- union query here 

end 
else 
begin 
    -- non union query here 

end 
+0

非常感謝這寶貴的建議。我認爲多語句表值函數具有與TEMPDB相關的性能損失。因爲這個查詢每5分鐘就會觸發一次,所以會引發很多爭論。請建議。 – rohit

+0

請嘗試看看。我認爲如果你將它分成幾部分,你的查詢的所有性能可能會更好。如果合適,您還可以在查詢表變量時在表變量()上定義主鍵以加快連接。我對從CTE返回的列感到困惑。您返回'VisitNumber'並在連接中使用'PatientChartId'。你也有一個'頂部',沒有'order by'。 –

+0

內聯TVF和多語句TVF之間的行爲差​​異在於,內聯被擴展到使用該函數的查詢中,使得查詢優化器能夠找出不同的計劃。基本上它將調用查詢中的函數替換爲內聯函數中的語句,然後開始創建查詢計劃。多語句TVF必須首先執行,然後將結果合併到外部查詢中。 –

相關問題