1

I have a table which has 13,0000 records, but without indexing and I have written a query which has 4 LEFT OUTER JOINs.

The query is working fine without any issue. My only concern is performance, it's taking 5-10 minutes to give the results. So my question is how can I improve the performance of the query? My second question is do I need to add indexes? If yes, which index should I add, cluster or non cluster?

My query is:

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
Sharad
  • 3,562
  • 6
  • 37
  • 59

1 Answers1

1

It looks to me that you can solve the entire query in one pass, by using conditional aggregation.

I haven't used SQL Server that much, so I don't exactly get the date logic, but as I understand you are calculating the amount over different time periods, like accumulated since the start of the year, since the start of the month, and todays amount etcetera.

For such a query, you are anyway touching all records with a BillDate between the start of the year and todays date. You should be able to use a query similar to the below. The idea is to SUM the amount only if the BillDate is in the time period.

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;

Let me know if you don't get this to work!

Ronnis
  • 12,593
  • 2
  • 32
  • 52