SUM individual dynamic columns from pivot table -SQL server/SAP B1 - sql

I writing a SQL server query for based on an SAP Business One DB, I have a dynamic list of columns that I am using in a PIVOT to create dynamic columns.im currently getting separate data since I pass though the "PrcName" into the group by for the Pivot.
I want to be able to sum each dynamic column in my #TEMP table to SUMing the individual "PrcName" Rows. Something lie this: SUM(' + #Columns + ')
The below query gives me something like this:
Type FatherAccount levels AcctCode AccntntCod AcctName Group1 Group2 Project1 Project2
Expense Cost 11 1000002 400002 Resource 0 0 1000 0
Expense Cost 11 1000002 400002 Resource 0 0 0 2000
But I trying to sum them into this:
Type FatherAccount levels AcctCode AccntntCod AcctName Group1 Group2 Project1 Project2
Expense Cost 11 1000002 400002 Resource 0 0 1000 2000
SQL query:
SELECT * INTO #TEMP FROM(
SELECT Type, FatherAccount, Levels, [AcctCode], [AccntntCod], [AcctName], [Tender], [OverHead], ' + #Columns + '
FROM
(SELECT
CASE WHEN T0.GroupMask IN (''4'') THEN ''Revenue'' ELSE ''Expense'' END AS "Type",
T5.AcctName AS "FatherAccount", ''11'' AS Levels, T0.[AcctCode], T0.[AccntntCod], T0.[AcctName],
CASE WHEN T2.PrcName LIKE ''%Group1%'' THEN SUM(T1.[Debit] - T1.[Credit])END AS Group1",
CASE WHEN T2.PrcName LIKE ''%Group2%'' THEN SUM(T1.[Debit] - T1.[Credit])END AS "Group1",
SUM(T1.[Debit] - T1.[Credit]) AS Balance,
T2.[PrcName] AS PrcName
,ROW_NUMBER() OVER(PARTITION BY T0.AcctName, SUM(T1.[Debit] - T1.[Credit]) ORDER BY T0.AcctCode DESC) rn
FROM OACT T0
LEFT JOIN JDT1 T1 ON T0.[AcctCode] = T1.[Account]
LEFT JOIN OPRC T2 ON T2.PrcCode = T1.ProfitCode
LEFT JOIN OPRC T3 ON T3.PrcCode = T1.OcrCode2
LEFT JOIN OPRC T4 ON T4.PrcCode = T1.OcrCode3
LEFT JOIN OACT T5 ON T5.AcctCode = T0.FatherNum
WHERE T0.GroupMask IN (''4'', ''5'', ''6'', ''7'') AND (T0.Postable = ''Y'')
AND ((T1.RefDate Between ''[%0]'' AND ''[%1]'') OR T0.CurrTotal = 0)
AND (T4.PrcName = ''[%2]'' OR T0.CurrTotal = 0)
--GROUP BY GROUPING SETS ((T0.Levels,T0.[AcctCode],T0.[AccntntCod], T0.[AcctName], T5.AcctName, T2.PrcName, T0.GroupMask),(T5.AcctName))
--GROUP BY T0.Levels,T0.[AcctCode],T0.[AccntntCod], T0.[AcctName], T5.AcctName, T2.PrcName, T0.GroupMask
) as PivotData
PIVOT
(
SUM(Balance)
FOR PrcName IN (' + #Columns + ')
) AS PivotResult
) AS #TEMP
SELECT T0.Type, T0.FatherAccount, T0.levels, T0.AcctCode, T0.AccntntCod, T0.AcctName, SUM(T0.Group1) AS Group1, SUM(T0.Group2) AS Group1, SUM(' + #Columns + ')
FROM #TEMP T0
GROUP BY T0.Type, T0.FatherAccount, T0.levels, T0.AcctCode, T0.AccntntCod, T0.AcctName, ' + #Columns + '
ORDER BY Type, Levels, FatherAccount
Thanks for the help!

Without adding the values from the PrcName column to the pivoted columns, does this query return correct output?
SELECT CASE WHEN T0.GroupMask IN ('4') THEN 'Revenue' ELSE 'Expense' END AS [Type],
T5.AcctName AS FatherAccount,
'11' AS Levels,
T0.[AcctCode],
T0.[AccntntCod],
T0.[AcctName],
T2.[PrcName] AS PrcName,
sum(CASE WHEN T2.PrcName LIKE '%Group1%' THEN (T1.[Debit] - T1.[Credit]) else 0 END) AS Group1,
sum(CASE WHEN T2.PrcName LIKE '%Group2%' THEN (T1.[Debit] - T1.[Credit]) else 0 END) AS Group2,
SUM(T1.[Debit] - T1.[Credit]) AS Balance
FROM OACT T0
LEFT JOIN JDT1 T1 ON T0.[AcctCode] = T1.[Account]
LEFT JOIN OPRC T2 ON T2.PrcCode = T1.ProfitCode
LEFT JOIN OPRC T3 ON T3.PrcCode = T1.OcrCode2
LEFT JOIN OPRC T4 ON T4.PrcCode = T1.OcrCode3
LEFT JOIN OACT T5 ON T5.AcctCode = T0.FatherNum
WHERE T0.GroupMask IN ('4', '5', '6', '7')
AND (T0.Postable = 'Y')
AND ((T1.RefDate Between '[%0]' AND '[%1]') OR T0.CurrTotal = 0)
AND (T4.PrcName = '[%2]' OR T0.CurrTotal = 0)
GROUP BY [Type], T5.AcctName, T0.[AcctCode], T0.[AccntntCod], T0.[AcctName], T2.PrcName;

Related

Calculate the running balance in SQL from Debit/Credit column with temporary variable?

I want to calculate running balance in SQL server but it is showing syntax error near '=' and ':=' operator. Don't know how to add values.
I am sharing my SQL query that I am using.
SQL query:
declare #tempbal decimal(18,0)
set #tempbal = (select top 1 (balance)
from t1
left outer join t2 on t2.accountno = t1.accountno
left outer join t3 on t1.cc = t2.dc
where accountNo = '1234')
select
'Date',
'Description',
isnull(case when t1.amount<0 then (t1.amount) end,0) as Debit,
isnull(case when t1.amount>0 then (t1.amount) end,0) as Credit,
(#tempbal = #tempbal + (t1.amount) as balance
from t1
left outer join t2 on t2.accountno = t1.accountno
left outer join t3 on t1.cc = t2.dc
where accountNo = '1234')
Here I am getting:
incorrect syntax error near '=' sign in select statement.
I have googled a lot but couldn't find a solution to resolve this. I have also used ':=' operator but it didn't work.
I am Adding output which I am getting after applying ' sum(t1.balance+t1.amount) as balance '
Here balance column has value 5970.12 on the basis of this I got this....I also mentioned the expected output.
Date | Desc | Amount | Balance | Expected Balance
2020-01-01 |Ref12 | 6.8 | 5976.92 | 5976.92
2020-01-06 |ref34 | 850 | 6820.12 | 6826.92
2020-01-22 |ref44 | 22032 | 28002.12 | 28858.92
2020-02-07 |ref54 | -26000 | -20029.88 | 2858.92
Please, help me out of this mess...
Thanks
You can use SUM() OVER( ORDER BY ... ) for running total
your query can be as follow
select [Date],
[Description],
isnull(case when t1.amount<0 then (t1.amount) end,0) as Debit,
isnull(case when t1.amount>0 then (t1.amount) end,0) as Credit,
SUM(t1.amount) OVER (ORDER BY [Date]) as balance
from t1
left outer join t2 on t2.accountno = t1.accountno
left outer join t3 on t1.cc = t2.dc
where t1.accountNo = '1234'
Updated Query :
added initial balance from first row to the running balance.
select [Date],
[Description],
isnull(case when t1.amount<0 then (t1.amount) end,0) as Debit,
isnull(case when t1.amount>0 then (t1.amount) end,0) as Credit,
case when row_number() over (order by [Date]) = 1
then balance
else 0
end
+ SUM(t1.amount) OVER (ORDER BY [Date]) as balance
from t1
left outer join t2 on t2.accountno = t1.accountno
left outer join t3 on t1.cc = t2.dc
where t1.accountNo = '1234'

Oracle Join - Which is faster - using the whole table or a subquery that has specific columns needed in the table?

I am really new into optimizing queries. Could you please advise which INNER JOIN runs faster?
Please note that i am using two different ways of inner join syntax(have same # of records)
1.) INNER JOIN of subqueries that have DISTINCT and selected columns only from its respective table
select
fac.fac_id ,
dept.dept_id ,
wk.week_id ,
sum(case when TRIM(fpl.MEASURE) like '%Salar%Wage%' then DATAVALUE else 0 end) WAGES_AMT,
sum(case when TRIM(fpl.MEASURE) like '%Tot%Man%hour%Ret%' then DATAVALUE else 0 end) MANHRS_QTY,
fpl.md_cycle_nbr ,
fpl.md_load_dt
from
EAS_STG.FPA_PLAN_LABOR fpl
INNER JOIN
(
select distinct(dept_nbr), dept_id
from department_D
where regexp_instr( Dept_nbr,'([^0-9])') = 0
) dept
ON TO_NUMBER(TRIM( 'D' FROM fpl.department)) = TO_NUMBER(dept.dept_nbr)
INNER JOIN
(
select distinct(FAC.FAC_NBR), fai.fac_id
from FACILITY_D fac, FACILITY_ALTERNATE_ID fai
where fac.fac_id = fai.fac_id
and fac.company_id = 1101
) fac
ON TRIM(REPLACE(fpl.facility, 'Fac-')) = fac.fac_nbr
INNER JOIN
(
select distinct(wk_hierarchy_id) week_id from DAY_HIERARCHY_D
) wk ON TO_NUMBER(TRIM(REPLACE(fpl.scenario, 'Plan ')) || TRIM(REPLACE(fpl.time, 'Wk '))) = WK.week_id
GROUP BY
fac.fac_id ,
dept.dept_id ,
wk.week_id ,
fpl.md_cycle_nbr ,
fpl.md_load_dt
;
2.) INNER JOIN of the whole table without the selected columns
SELECT fac.fac_id
, dept.dept_id
, d.wk_hierarchy_id week_id
, SUM(CASE WHEN TRIM(fpl.MEASURE) LIKE '%Salar%Wage%' THEN datavalue ELSE 0 END) WAGES_AMT
, SUM(CASE WHEN TRIM(fpl.MEASURE) LIKE '%Tot%Man%hour%Ret%' THEN datavalue ELSE 0 END) MANHRS_QTY
, fpl.md_cycle_nbr
, fpl.md_load_dt
FROM EAS_STG.FPA_PLAN_LABOR fpl
JOIN department_d dept
ON TO_NUMBER(TRIM( 'D' FROM fpl.department)) = TO_NUMBER(dept.dept_nbr)
JOIN facility_d fac
ON TRIM(REPLACE(fpl.facility, 'Fac-')) = fac.fac_nbr
JOIN facility_alternate_id fai
ON fac.fac_id = fai.fac_id
JOIN day_hierarchy_d d
ON TO_NUMBER(TRIM(REPLACE(fpl.scenario, 'Plan ')) || TRIM(REPLACE(fpl.time, 'Wk '))) = d.wk_hierarchy_id
WHERE fac.company_id = 1101
AND REGEXP_INSTR(dept_nbr,'([^0-9])') = 0
GROUP BY fac.fac_id
, dept.dept_id
, d.wk_hierarchy_id
, fpl.md_cycle_nbr
, fpl.md_load_dt
;

Top 1 Item from the List in SQL

I have the following scenario
I am getting Output like this
Month Product Name Amount
Jan-2014 A-Prodcut 50
Jan-2014 B-Product 45
Jan-2014 C-Product 55
Feb-2014 A-Prodcut 60
Feb-2014 B-Product 48
Feb-2014 C-Product 80
I want Output like this :
Jan-2014 C-Product 55
Feb-2014 C-Product 80
I want top product from each month How to achieve this
Here is my query
;With cte as
(
SELECT #EndDate AS TheMonth, 0 as [Counter]
UNION ALL
SELECT DATEADD(mm,-[Counter] -1,#EndDate), Counter + 1 AS TheMonth
from cte
WHERE DATEADD(mm,-[Counter] -1,#EndDate) >= #StartDate
)
SELECT
left(DATENAME(MM,TheMonth),3) +'-'+ cast(year(TheMonth) as varchar) AS [Month-Year],
ISNULL(IM.product_name,'N/A') as 'Product Name',
isnull(sum((ism.selling_price * siim.qty) + (((tm.tax_amount*(ism.selling_price * siim.qty))/100))),0) AS Amount
FROM
cte
LEFT OUTER JOIN RS_Sell_Order_Master AS SM on MONTH(invoice_date) = MONTH(TheMonth)
AND YEAR(invoice_date) = YEAR(TheMonth)
AND sm.is_approved = 1
LEFT OUTER JOIN RS_Sells_Invoice_Info_Master AS SIIM ON SM.sell_order_no = SIIM.sell_order_no
LEFT OUTER JOIN RS_Inventory_Master AS IM ON SIIM.product_id = IM.product_id
LEFT OUTER JOIN RS_Tax_Master AS TM ON TM.tax_id = SIIM.tax_id
LEFT OUTER JOIN RS_Inventory_Selling_Master AS ISM ON ISM.selling_product_id = SIIM.selling_product_id
GROUP BY
IM.product_name,
TheMonth
Use Row_number() in the select query ie.
SELECT MONTH, PRODUCT_NAME, AMOUNT
FROM (
SELECT MONTH, PRODUCT_NAME, AMOUNT,
ROW_NUMBER ( )
OVER (PARTITION BY Month order by amount Desc) AS RANK
)
WHERE RANK = 1
Hope this helps..
Try this:
SELECT *
FROM
(
SELECT [Month-Year], [Product Name], Amount, ROW_NUMBER() OVER (Partition BY [Month-Year] ORDER BY Amount DESC) as rn
FROM
(
SELECT
left(DATENAME(MM,TheMonth),3) +'-'+ cast(year(TheMonth) as varchar) AS [Month-Year],
ISNULL(IM.product_name,'N/A') as 'Product Name',
isnull(sum((ism.selling_price * siim.qty) + (((tm.tax_amount*(ism.selling_price * siim.qty))/100))),0) AS Amount
FROM
cte
LEFT OUTER JOIN RS_Sell_Order_Master AS SM on MONTH(invoice_date) = MONTH(TheMonth)
AND YEAR(invoice_date) = YEAR(TheMonth)
AND sm.is_approved = 1
LEFT OUTER JOIN RS_Sells_Invoice_Info_Master AS SIIM ON SM.sell_order_no = SIIM.sell_order_no
LEFT OUTER JOIN RS_Inventory_Master AS IM ON SIIM.product_id = IM.product_id
LEFT OUTER JOIN RS_Tax_Master AS TM ON TM.tax_id = SIIM.tax_id
LEFT OUTER JOIN RS_Inventory_Selling_Master AS ISM ON ISM.selling_product_id = SIIM.selling_product_id
GROUP BY
IM.product_name,
TheMonth
) a
)b
WHERE rn = 1
Usually OUTER APPLY or CROSS APPLY is a way to go in theese situations.
So your SELECT would be like this:
;With cte as
(
SELECT #EndDate AS TheMonth, 0 as [Counter]
UNION ALL
SELECT DATEADD(mm,-[Counter] -1,#EndDate), Counter + 1 AS TheMonth
from cte
WHERE DATEADD(mm,-[Counter] -1,#EndDate) >= #StartDate
)
SELECT
left(DATENAME(MM,TheMonth),3) +'-'+ cast(year(TheMonth) as varchar) AS [Month-Year],
'Product Name', Amount
FROM
cte
OUTER APPLY ( SELECT TOP 1
ISNULL(IM.product_name,'N/A') as 'Product Name',
isnull(sum((ism.selling_price * siim.qty) +
(((tm.tax_amount*(ism.selling_price * siim.qty))/100))),0) AS Amount
FROM RS_Sell_Order_Master AS SM
LEFT OUTER JOIN RS_Sells_Invoice_Info_Master AS SIIM
ON SM.sell_order_no = SIIM.sell_order_no
LEFT OUTER JOIN RS_Inventory_Master AS IM
ON SIIM.product_id = IM.product_id
LEFT OUTER JOIN RS_Tax_Master AS TM
ON TM.tax_id = SIIM.tax_id
LEFT OUTER JOIN RS_Inventory_Selling_Master AS ISM
ON ISM.selling_product_id = SIIM.selling_product_id
WHERE MONTH(invoice_date) = MONTH(TheMonth) AND YEAR(invoice_date) = YEAR(TheMonth) AND sm.is_approved = 1
ORDER BY Amount DESC
) x
GROUP BY
'Product Name',
TheMonth

Trying to join two sql statement

I would like to join Query 1 and Query 2 on TripId.
Query 1
SELECT tblTrips.TripId,tblVehicles.VehicleNo
FROM tblTrips INNER JOIN tblVehicles ON tblTrips.VehicleId = tblVehicles.VehicleId
Query 2
;with T1 as (
SELECT tblTrips.TripId, tblTripDeductions.Amount, CONVERT(VARCHAR(400),tblDeductionTypes.DeductionType+' - '+tblTripDeductions.Description+' - '+ CONVERT(VARCHAR(24),tblTripDeductions.Amount)) as DeductionFor
FROM tblTrips INNER JOIN
tblTripDeductions ON tblTrips.TripId = tblTripDeductions.TripId INNER JOIN
tblDeductionTypes ON tblTripDeductions.DeductionId = tblDeductionTypes.DeductionId
)select **T1.TripId**, SUM(T1.Amount) as Amount, stuff((select '#',' ' + CONVERT(varchar(1000),T2.DeductionFor) from T1 AS T2 where T1.TripId = T2.TripId for xml path('')),1,1,'') [Description] from T1
Group by TripId
First query's output is list of TripId and VehicleNo.
Second query's output is list of TripId, Amount and description.
And my desire output is TripId, VehicleNo, amount and description.
The Syntax for WITH (Common Table Expressions) allows you to create multiple CTE's.
Using that you can turn your final part of Query2 in to a CTE (Which I'll name Query2) and your query for Query1 can also be made in to a CTE (which I'll name Query1).
Then, the final SELECT statement can simply join those two CTE's together.
;
WITH
T1 as (
SELECT tblTrips.TripId, tblTripDeductions.Amount, CONVERT(VARCHAR(400),tblDeductionTypes.DeductionType+' - '+tblTripDeductions.Description+' - '+ CONVERT(VARCHAR(24),tblTripDeductions.Amount)) as DeductionFor
FROM tblTrips INNER JOIN
tblTripDeductions ON tblTrips.TripId = tblTripDeductions.TripId INNER JOIN
tblDeductionTypes ON tblTripDeductions.DeductionId = tblDeductionTypes.DeductionId
)
,
Query2 AS (
select **T1.TripId**, SUM(T1.Amount) as Amount, stuff((select '#',' ' + CONVERT(varchar(1000),T2.DeductionFor) from T1 AS T2 where T1.TripId = T2.TripId for xml path('')),1,1,'') [Description] from T1
Group by TripId
)
,
Query1 AS (
<Your Code For Query1>
)
SELECT
*
FROM
Query1
INNER JOIN
Query2
ON Query1.TripID = Query2.TripID
I haven't don't anything to check your queries, as the layout that you have used isn't very readable.
Just merge the queries using CTE (didn't change/review your code, just formatted it for the sake of readability - input was pretty horrible to read)
;WITH T1 AS (
SELECT tblTrips.TripId
, tblTrips.DestinationDistrictId
, tblTrips.VehicleId
, tblTrips.No
, tblVehicles.VehicleNo
, tblTrips.CoachNo
, CONVERT(VARCHAR(24), tblTrips.GoDate, 105) AS GoDate
, tblTrips.GoTime
, CASE WHEN tblTrips.IsCome=1
THEN CONVERT(VARCHAR(24), tblTrips.ComeDate, 105)
ELSE '-'
END AS ComeDate
, CASE WHEN tblTrips.IsCome=1
THEN tblTrips.ComeTime
ELSE '-'
END AS ComeTime
, CASE WHEN tblTrips.IsCome=1
THEN (SD.DistrictName + ' - ' + DD.DistrictName + ' - ' + SD.DistrictName)
ELSE (SD.DistrictName + ' - ' + DD.DistrictName)
END AS Destination
, tblSupervisors.Name AS Supervisor
, tblDrivers.Name AS Driver
, tblTrips.AdvanceAmount
, tblTrips.AdvanceDescription
FROM tblTrips
INNER JOIN tblSupervisors ON tblTrips.SuperVisorId = tblSupervisors.SupervisorId
INNER JOIN tblDrivers ON tblTrips.DriverId = tblDrivers.DriverId
INNER JOIN tblDistricts SD ON tblTrips.StartDistrictId = SD.DistrictId
INNER JOIN tblDistricts DD ON tblTrips.DestinationDistrictId = DD.DistrictId
INNER JOIN tblVehicles ON tblTrips.VehicleId = tblVehicles.VehicleId
)
, Q1 AS (
SELECT T1.TripId
, SUM(T1.Amount) AS Amount
, STUFF((
SELECT '#', ' ' + CONVERT(VARCHAR(MAX), T2.DeductionFor)
FROM T1 AS T2
WHERE T1.TripId = T2.TripId FOR XML PATH(''))
,1,1,'') AS [Description]
FROM T1
GROUP BY TripId
)
, Q2 AS (
SELECT tblTrips.TripId
, tblTripDeductions.Amount
, CONVERT(VARCHAR(400), tblDeductionTypes.DeductionType + ' - ' + tblTripDeductions.Description + ' - ' + CONVERT(VARCHAR(24), tblTripDeductions.Amount)) AS DeductionFor
FROM tblTrips
INNER JOIN tblTripDeductions ON tblTrips.TripId = tblTripDeductions.TripId
INNER JOIN tblDeductionTypes ON tblTripDeductions.DeductionId = tblDeductionTypes.DeductionId
)
SELECT *
FROM Q1
INNER JOIN Q2 ON Q1.TripId = Q2.TripId

How to Optimize this query (stuff part)

How can I Optimize this following query:
SELECT
MONTH('1' + LEFT(Datename(month,visitDate),3) +'00') AS MONTH_NUMBER ,
VisitMonth = LEFT(Datename(month,visitDate),3)
,TotalVisits = Count(v.VisitID)
,TotalVisits_with_StandardReport = Count(CASE WHEN v.ReportStandard NOT IN (0,9) THEN v.ReportStandard END)
,TotalVisits_with_FeedbackReport = Count(CASE WHEN v.DiscrepancyType IN (2,5) THEN v.DiscrepancyStatus END)
,Perc =
CAST(100 - ISNULL(CAST((Count(CASE WHEN v.DiscrepancyType IN (2,5) THEN v.DiscrepancyType END) * 1.0 / Count(CASE WHEN v.ReportStandard NOT IN (0,9) THEN v.ReportStandard END)) * 100 AS FLOAT),0) AS NUMERIC(10,2))
,VisitAssignmentID_with_FeedbackRpt = STUFF (( SELECT ', ' + CAST(v2.AssignmentID AS VARCHAR) from Visits v2
INNER JOIN
Assignments a2 ON a2.AssignmentID = v2.AssignmentID
WHERE
DATENAME(MONTH,v.VisitDate) = DATENAME(MONTH,v2.VisitDate)
AND a2.ClientID IN (22,33) AND v2.DiscrepancyType IN (2,5)
GROUP BY V2.AssignmentID
FOR xml path('')), 1, 2, '')
FROM Visits v
INNER JOIN Assignments a ON a.AssignmentID = v.AssignmentID
WHERE a.ClientID IN (22,33)
AND v.VisitDate BETWEEN '01/01/2013' AND '31/12/2013'
GROUP BY DATENAME(MONTH,v.VisitDate)
ORDER BY MONTH_NUMBER
Result
Second query which i tried to simplify and optimize (but query results are not same)
I have tried to optimize the query and tried to simply the stuff inner query but i am not getting the results i want. It has reduced the total execution time though but results are not same.
WITH ALL_CTE(MONTH_NUMBER,VisitMonth,VisitID,AssignmentID,ReportStandard,DiscrepancyStatus,DiscrepancyType,VisitA ssignmentID_with_FeedbackRpt)
AS
-- Define the CTE query.
(
SELECT
MONTH('1' + LEFT(Datename(month,visitDate),3) +'00') AS MONTH_NUMBER ,
VisitMonth = LEFT(Datename(month,visitDate),3)
,v.VisitID, v.AssignmentID , v.ReportStandard , v.DiscrepancyStatus, v.DiscrepancyType
,VisitAssignmentID_with_FeedbackRpt =
STUFF (( SELECT ', ' + CAST((CASE WHEN DiscrepancyType IN (2,5) THEN v.AssignmentID END) AS VARCHAR)
FOR xml path('')), 1, 2, '')
FROM Visits v
INNER JOIN Assignments a ON a.AssignmentID = v.AssignmentID
WHERE a.ClientID IN (22,33)
AND v.VisitDate BETWEEN '01/01/2013' AND '31/12/2013'
group by v.AssignmentID,visitDate,VisitID,ReportStandard,DiscrepancyStatus,DiscrepancyType
)
-- Define the outer query referencing the CTE name.
SELECT
MONTH_NUMBER
,VisitMonth
,COUNT(VisitID)
,TotalVisits_with_StandardReport = COUNT(CASE WHEN ReportStandard NOT IN (0,9) THEN ReportStandard END)
,TotalVisits_with_FeedbackReport = COUNT(CASE WHEN DiscrepancyType IN (2,5) THEN DiscrepancyStatus END)
,isnull(VisitAssignmentID_with_FeedbackRpt,0)
FROM ALL_CTE
GROUP BY MONTH_NUMBER,VisitMonth,VisitAssignmentID_with_FeedbackRpt
Client Stats
I think the only real optimization you can do here is make sure that you have an index on AssignmentID so that the inner join is quicker. All the other parts are pretty irrelevant, they are just conversions handled in memory.