我有一个包含13,0000条记录的表,但是没有索引,我编写了一个有4个LEFT OUTER JOIN的查询。
查询工作正常,没有任何问题。我唯一担心的是性能,需要5-10分钟才能得出结果。所以我的问题是我如何才能提高查询的性能?我的第二个问题是我需要添加索引吗?如果是,我应该添加哪个索引,群集还是非群集?
我的查询:
SELECT Z.* FROM
(SELECT
YTD.Specialisation,
YTD.SpecialisationCode,
ROUND(COALESCE(Today.Revenue_Today,0),0)Revenue_Today,
ROUND(COALESCE(MTD.Revenue_MTD,0),0)Revenue_MTD,
ROUND(COALESCE(YTD.Revenue_YTD,0),0)Revenue_YTD,
ROUND(COALESCE(DTD.Revenue_DTD,0),0)Revenue_DTD,
ROUND(COALESCE(Today.Amount1_Today,0),0)Amount1_Today,
ROUND(COALESCE(MTD.Amount1_MTD,0),0)Amount1_MTD,
ROUND(COALESCE(YTD.Amount1_YTD,0),0)Amount1_YTD,
ROUND(COALESCE(DTD.Amount1_DTD,0),0)Amount1_DTD,
ROUND(COALESCE(Today.Amount2_Today,0),0)Amount2_Today,
ROUND(COALESCE(MTD.Amount2_MTD,0),0)Amount2_MTD,
ROUND(COALESCE(YTD.Amount2_YTD,0),0)Amount2_YTD,
ROUND(COALESCE(DTD.Amount2_DTD,0),0)Amount2_DTD,
ROUND(COALESCE(Today.Amount3_Today,0),0)Amount3_Today,
ROUND(COALESCE(MTD.Amount3_MTD,0),0)Amount3_MTD,
ROUND(COALESCE(YTD.Amount3_YTD,0),0)Amount3_YTD,
ROUND(COALESCE(DTD.Amount3_DTD,0),0)Amount3_DTD,
ROUND(COALESCE(Today.Amount4_Today,0),0)Amount4_Today,
ROUND(COALESCE(MTD.Amount4_MTD,0),0)Amount4_MTD,
ROUND(COALESCE(YTD.Amount4_YTD,0),0)Amount4_YTD,
ROUND(COALESCE(DTD.Amount4_DTD,0),0)Amount4_DTD,
ROUND(COALESCE(Today.Amount5_Today,0),0)Amount5_Today,
ROUND(COALESCE(MTD.Amount5_MTD,0),0)Amount5_MTD,
ROUND(COALESCE(YTD.Amount5_YTD,0),0)Amount5_YTD,
ROUND(COALESCE(DTD.Amount5_DTD,0),0)Amount5_DTD
FROM
(select
a.SpecialisationCode,
a.Specialisation,
SUM(a.DoctorFee)Revenue_YTD,
SUM(a.Amount1)Amount1_YTD,
SUM(a.Amount2)Amount2_YTD,
SUM(a.Amount3)Amount3_YTD,
SUM(a.Amount4)Amount4_YTD,
SUM(a.Amount5)Amount5_YTD
from tbl_doctor a
where FORMAT((CONVERT(smalldatetime,a.BillDate,111)),'yyyy-MM-dd') >= FORMAT((CONVERT(smalldatetime,'2012-04-01',111)),'yyyy-04-01')
AND FORMAT((CONVERT(smalldatetime,a.BillDate,111)),'yyyy-MM-dd') <= '2012-05-01'
and a.SpecialisationCode!=0
and a.Specialisation NOT IN (' ')
GROUP BY a.SpecialisationCode,a.Specialisation)YTD
LEFT OUTER JOIN
(select
a.SpecialisationCode,
a.Specialisation,
SUM(a.DoctorFee)Revenue_DTD,
SUM(a.Amount1)Amount1_DTD,
SUM(a.Amount2)Amount2_DTD,
SUM(a.Amount3)Amount3_DTD,
SUM(a.Amount4)Amount4_DTD,
SUM(a.Amount5)Amount5_DTD
from tbl_doctor a
where FORMAT((CONVERT(smalldatetime,a.BillDate,111)),'yyyy-MM-dd') >= '2012-04-01'
AND FORMAT((CONVERT(smalldatetime,a.BillDate,111)),'yyyy-MM-dd') <= '2012-05-01'
and a.SpecialisationCode!=0
and a.Specialisation NOT IN (' ')
GROUP BY a.SpecialisationCode,a.Specialisation)DTD
ON DTD.SpecialisationCode=YTD.SpecialisationCode
LEFT OUTER JOIN
(select
a.SpecialisationCode,
a.Specialisation,
SUM(a.DoctorFee)Revenue_MTD,
SUM(a.Amount1)Amount1_MTD,
SUM(a.Amount2)Amount2_MTD,
SUM(a.Amount3)Amount3_MTD,
SUM(a.Amount4)Amount4_MTD,
SUM(a.Amount5)Amount5_MTD
from tbl_doctor a
where FORMAT((CONVERT(smalldatetime,a.BillDate,111)),'yyyy-MM-dd') >= FORMAT((CONVERT(smalldatetime,'2012-05-01',111)),'yyyy-MM-01')
AND FORMAT((CONVERT(smalldatetime,a.BillDate,111)),'yyyy-MM-dd') <= FORMAT((CONVERT(smalldatetime,eomonth('2012-05-01'),111)),'yyyy-MM-dd')
and a.SpecialisationCode!=0
and a.Specialisation NOT IN (' ')
GROUP BY a.SpecialisationCode,a.Specialisation)MTD
ON YTD.SpecialisationCode=MTD.SpecialisationCode
LEFT OUTER JOIN
(select
a.SpecialisationCode,
a.Specialisation,
COALESCE(SUM(a.DoctorFee),0)Revenue_Today,
SUM(a.Amount1)Amount1_Today,
SUM(a.Amount2)Amount2_Today,
SUM(a.Amount3)Amount3_Today,
SUM(a.Amount4)Amount4_Today,
SUM(a.Amount5)Amount5_Today
from tbl_doctor a
where FORMAT((CONVERT(smalldatetime,a.BillDate,111)),'yyyy-MM-dd') = '2012-05-01'
and a.SpecialisationCode!=0
and a.Specialisation NOT IN (' ')
GROUP BY a.SpecialisationCode,a.Specialisation)Today
ON YTD.SpecialisationCode=Today.SpecialisationCode ) z
order by z.Specialisation
答案 0 :(得分:1)
在我看来,您可以通过使用条件聚合一次解决整个查询。
我没有那么多地使用SQL Server,所以我没有完全得到日期逻辑,但据我所知,你正在计算不同时间段的金额,比如自年初以来积累的金额,自开始以来本月,以及今天的数量等等。
对于此类查询,您无论如何都会在年初和今天之间触摸BillDate
的所有记录。您应该能够使用类似于下面的查询。这个想法是只有在BillDate处于时间段内时才计入金额。
select a.SpecialisationCode
,a.Specialisation
,sum(case when a.BillDate = today then a.Amount1 end) as Amount1_Today
,sum(case when a.BillDate between date 'first-day-in-month' and today then a.Amount1 end) as Amount1_MTD
,sum(a.Amount1) as Amount1_YTD
from tbl_doctor
where a.SpecialisationCode!=0
and a.Specialisation NOT IN (' ')
and a.BillDate between date 'first day in year'
and date 'today'
group
by a.SpecialisationCode
,a.Specialisation;
如果你没有让它发挥作用,请告诉我!