2012-10-16 35 views
0

我沒有權限在這些表上不幸地設置索引。如何在加入WITH時防止可怕的表現

前兩個WITH's導致此查詢運行幾個小時:

;with OneAccession as (
select client_id,COUNT(patient_id) PatientCount from 
(
select client_id,patient_id 
from F_ACCESSION_DAILY 
group by CLIENT_ID,PATIENT_ID 
having COUNT(ACCESSION_ID)=1 
) a 
group by CLIENT_ID 
) 
, 

TwoAccessions as (
select client_id,COUNT(patient_id) PatientCount from 
(
select client_id,patient_id 
from F_ACCESSION_DAILY 
group by CLIENT_ID,PATIENT_ID 
having COUNT(ACCESSION_ID)=2 
) a 
group by client_id 
) 



select 
f.client_id 
, 12*(year(getdate())-year(min(f.received_date))) + MONTH(GETDATE())-MONTH(min(f.received_date)) 
, COUNT(distinct f.patient_id) TotalPatients 
, COUNT(f.ACCESSION_ID) TotalSpecimens 
, o.PatientCount TotalPatientsWOneSpec 
, t.PatientCount TotalPatientsWTwoSpec 
from F_ACCESSION_DAILY f 
join 
OneAccession o 
on o.CLIENT_ID=f.CLIENT_ID 
join 
TwoAccessions t 
on t.client_id=f.CLIENT_ID 
where f.CLIENT_ID not in (select clientid from SalesDWH..TestPractices) 
and f.SPECIMEN_SOURCE in ('Oral Fluid','Urine') 
group by f.CLIENT_ID,o.PatientCount,t.PatientCount 

如果我刪除OneAccessionTwoAccessions,我可以在短短几分鐘的結果!

我將非常感謝任何關於改進我的查詢語法的指導,以加快速度!

非常感謝。

回答

4

你能避免所有的,如果你只是做兩分組依據的聯接。 首先計算每個客戶的標本,病人 然後結合這些計數每個客戶端:

WITH SpecimenCountPerPatient AS(
    SELECT client_id, patient_id, COUNT(1) SpecimenCount, MIN(received_date) FirstSpecimenDate 
    FROM dbo.F_ACCESSION_DAILY 
    GROUP BY client_id, patient_id 
) 
SELECT client_id, 
     DATEDIFF(Month,MIN(FirstSpecimenDate),GETDATE()) FirstSpecimenAgeInMonthForClient, 
     COUNT(1) TotalPatients, 
     SUM(SpecimenCount) TotalSpecimens, 
     SUM(CASE WHEN SpecimenCount = 1 THEN 1 ELSE 0 END) TotalPatientsWOneSpec, 
     SUM(CASE WHEN SpecimenCount = 2 THEN 1 ELSE 0 END) TotalPatientsWTwoSpec 
FROM SpecimenCountPerPatient 
GROUP BY client_id; 

這裏是一個SQLFiddle看到它在行動:http://sqlfiddle.com/#!3/72e40/2

現在,我知道你說你不能添加索引,但client_id ASC上的索引,patient_id ASC INCLUDE(received_date)會加快速度。

2

試試這個,讓我知道,如果它提高了性能

SELECT client_id,patient_id ,Accession_Id_Count = COUNT(ACCESSION_ID) 
INTO #temp 
from F_ACCESSION_DAILY 
group by CLIENT_ID,PATIENT_ID 

select 
f.client_id 
, 12*(year(getdate())-year(min(f.received_date))) + MONTH(GETDATE())-MONTH(min(f.received_date)) 
, COUNT(distinct f.patient_id) TotalPatients 
, COUNT(f.ACCESSION_ID) TotalSpecimens 
, o.PatientCount TotalPatientsWOneSpec 
, t.PatientCount TotalPatientsWTwoSpec 
from F_ACCESSION_DAILY f 
join (select client_id,COUNT(patient_id) PatientCount from #temp where Accession_Id_Count = 1 group by CLIENT_ID) o on o.CLIENT_ID=f.CLIENT_ID 
join (select client_id,COUNT(patient_id) PatientCount from #temp where Accession_Id_Count = 2 group by CLIENT_ID) t on t.client_id=f.CLIENT_ID 
where f.CLIENT_ID not in (select clientid from SalesDWH..TestPractices) 
and f.SPECIMEN_SOURCE in ('Oral Fluid','Urine') 
group by f.CLIENT_ID,o.PatientCount,t.PatientCount 

drop table #temp 
相關問題