Related
I have a query where there is a lot of repetitions of one condition. I am wondering - is it possible to put this condition into variable or something like that, so not the whole sentence is repeated each time?
The part which is repeating:
ISNULL((CASE WHEN IS_HOLIDAY = 1 THEN 2.5 * NETO_HOUR
WHEN DAY_IN_WEEK = 'Sunday' THEN NETO_HOUR END),0)
In query it looks like this:
UPDATE #tblALL_HOURS SET REG_WORK_COST = (CASE WHEN MINUTE_FROM >= 0 AND MINUTE_FROM <= #6h AND MINUTE_TO >= #6h AND MINUTE_TO <= #18h
AND IS_ABSENT = 0
THEN (DATEDIFF(MINUTE, DATEADD(MINUTE, #6h, CAST(CAST(DATE_TO AS DATE) AS DATETIME)), date_to)/60.00) * (BRUTO_HOUR + ISNULL((CASE WHEN IS_HOLIDAY = 1 THEN 2.5 * NETO_HOUR WHEN DAY_IN_WEEK = 'Sunday' THEN NETO_HOUR END),0))
WHEN MINUTE_FROM >= 0 AND MINUTE_FROM <= #6h AND MINUTE_TO >= #18h AND MINUTE_TO < #24h
AND IS_ABSENT = 0
THEN 12.00 * (BRUTO_HOUR + ISNULL((CASE WHEN IS_HOLIDAY = 1 THEN 2.5 * NETO_HOUR WHEN DAY_IN_WEEK = 'Sunday' THEN NETO_HOUR END),0))
WHEN MINUTE_FROM >= #6h AND MINUTE_FROM <= #18h AND MINUTE_TO >= #6h AND MINUTE_TO <= #18h
AND IS_ABSENT = 0
THEN (DATEDIFF(MINUTE, DATE_FROM, DATE_TO) / 60.00) * (BRUTO_HOUR + ISNULL((CASE WHEN IS_HOLIDAY = 1 THEN 2.5 * NETO_HOUR WHEN DAY_IN_WEEK = 'Sunday' THEN NETO_HOUR END),0))
WHEN MINUTE_FROM >= #6h AND MINUTE_FROM <= #18h AND MINUTE_TO >= #18h AND MINUTE_TO < #24h
AND IS_ABSENT = 0
THEN (DATEDIFF(MINUTE, DATE_FROM, DATEADD(MINUTE, #18h, CAST(CAST(DATE_FROM AS DATE) AS DATETIME))) / 60.00) * (BRUTO_HOUR + ISNULL((CASE WHEN IS_HOLIDAY = 1 THEN 2.5 * NETO_HOUR WHEN DAY_IN_WEEK = 'Sunday' THEN NETO_HOUR END),0))
END)
Is it possible to have something like this instead:
WHEN MINUTE_FROM >= #6h AND MINUTE_FROM <= #18h AND MINUTE_TO >= #18h AND MINUTE_TO < #24h AND IS_ABSENT = 0 THEN (DATEDIFF(MINUTE, DATE_FROM, DATEADD(MINUTE, #18h, CAST(CAST(DATE_FROM AS DATE) AS DATETIME))) / 60.00) * (BRUTO_HOUR + #myCondition)
Use a simple CTE that returns all the columns of #tblALL_HOURS and the value returned by ISNULL function:
ISNULL(CASE WHEN IS_HOLIDAY = 1 THEN 2.5 * NETO_HOUR WHEN DAY_IN_WEEK = 'Sunday' THEN NETO_HOUR END,0)
as a column and then update With the CTE and use that column in place of the condition:
WITH cte AS (
SELECT *,
ISNULL(CASE WHEN IS_HOLIDAY = 1 THEN 2.5 * NETO_HOUR WHEN DAY_IN_WEEK = 'Sunday' THEN NETO_HOUR END,0) AS myCondition
FROM #tblALL_HOURS
)
UPDATE cte
SET REG_WORK_COST = CASE
WHEN MINUTE_FROM >= 0 AND MINUTE_FROM <= #6h AND MINUTE_TO >= #6h AND MINUTE_TO <= #18h AND IS_ABSENT = 0
THEN (DATEDIFF(MINUTE, DATEADD(MINUTE, #6h, CAST(CAST(DATE_TO AS DATE) AS DATETIME)), date_to)/60.00) * (BRUTO_HOUR + myCondition)
WHEN MINUTE_FROM >= 0 AND MINUTE_FROM <= #6h AND MINUTE_TO >= #18h AND MINUTE_TO < #24h AND IS_ABSENT = 0
THEN 12.00 * (BRUTO_HOUR + myCondition)
WHEN MINUTE_FROM >= #6h AND MINUTE_FROM <= #18h AND MINUTE_TO >= #6h AND MINUTE_TO <= #18h AND IS_ABSENT = 0
THEN (DATEDIFF(MINUTE, DATE_FROM, DATE_TO) / 60.00) * (BRUTO_HOUR + myCondition)
WHEN MINUTE_FROM >= #6h AND MINUTE_FROM <= #18h AND MINUTE_TO >= #18h AND MINUTE_TO < #24h AND IS_ABSENT = 0
THEN (DATEDIFF(MINUTE, DATE_FROM, DATEADD(MINUTE, #18h, CAST(CAST(DATE_FROM AS DATE) AS DATETIME))) / 60.00) * (BRUTO_HOUR + myCondition)
END
I'm trying to get the salary of an employee and I'm not sure why ISNULL is not working here. Although the same query works when used outside subquery.
Maybe I'm implementing the Isnull function wrong.
Net salary is showing null even there is basic pay given.
DECLARE #dateFrom datetime
SET #dateFrom = '2018-03-01'
DECLARE #dateTo datetime
SET #dateTo = '2018-03-31'
Select
[Emp].ID
,[Emp].EmpCode
,[Emp].FirstName + ' ' + [Emp].LastName AS Name
,[Emp].BasicPay
,((select SUM(InstallmentAmount) from HRM.tbl_EmployeeLoanInstallment [Loan]
LEFT JOIN HRM.tbl_EmployeeLoan [EmpLoan] ON [EmpLoan].ID = [Loan].EmployeeLoanCode
where [EmpLoan].EmpCode = Emp.ID AND IsReceived != 1
AND CONVERT(date, [Loan].InstallmentDueOn) >= CONVERT(date, #dateFrom)
AND CONVERT(date, [Loan].InstallmentDueOn) <= CONVERT(date, #dateTo))) AS LoanDeduction
,( SELECT
(ISNULL([Info].[BasicPay], 0))
-
(SELECT SUM(ISNULL([Loan].InstallmentAmount, 0))
FROM [HRM].[tbl_EmployeeLoan] [EmpLoan]
FULL JOIN [HRM].[tbl_EmployeeInfo] [Info] ON [Info].[ID] = [EmpLoan].[EmpCode]
FULL JOIN [HRM].[tbl_EmployeeLoanInstallment] [Loan] ON [EmpLoan].[ID] = [Loan].[EmployeeLoanCode]
WHERE
CONVERT(date, [Loan].InstallmentDueOn) >= CONVERT(date, #dateFrom)
AND
CONVERT(date, [Loan].InstallmentDueOn) <= CONVERT(date, #dateTo)
AND
[Info].[ID] = [Emp].[ID]
GROUP BY Info.ID)
FROM
[HRM].[tbl_EmployeeInfo] [Info]
WHERE Info.ID = Emp.ID
GROUP BY [Info].[ID], [Info].[BasicPay]
) AS NetSalary
from HRM.tbl_EmployeeInfo [Emp]
Output:
412 C3-345 Ayesha Fatima 20000.00 NULL NULL
413 C3-651 Zainab Ali 20000.00 NULL NULL
414 C1343 Ahmed Abdullah 20000.00 11111.11 8888.89
415 231 Ahmed Aslam 20000.00 NULL NULL
416 FS-16 Fawaz Aslam 25000.00 NULL NULL
Are you sure that your subquery return a value? Seems to not be the case.
If you really want a value, you should catch your null value at the end of your subquery.
,ISNULL(
( SELECT
(ISNULL([Info].[BasicPay], 0))
-
(SELECT SUM(ISNULL([Loan].InstallmentAmount, 0))
FROM [HRM].[tbl_EmployeeLoan] [EmpLoan]
FULL JOIN [HRM].[tbl_EmployeeInfo] [Info] ON [Info].[ID] = [EmpLoan].[EmpCode]
FULL JOIN [HRM].[tbl_EmployeeLoanInstallment] [Loan] ON [EmpLoan].[ID] = [Loan].[EmployeeLoanCode]
WHERE
CONVERT(date, [Loan].InstallmentDueOn) >= CONVERT(date, #dateFrom)
AND
CONVERT(date, [Loan].InstallmentDueOn) <= CONVERT(date, #dateTo)
AND
[Info].[ID] = [Emp].[ID]
GROUP BY Info.ID)
, 0)
FROM
[HRM].[tbl_EmployeeInfo] [Info]
i have a table with the following data, i am trying to get the max and min columns from the table. if it is one column i can use max/min for the column, but here i am comparing all the column in a table. what i need is add new columns to store max and min data.
and there will be only one row in the table
create table
#test ( column1 int, column2 int , column3 int , column4 int ,column5 int,column6 int)
insert into #test
values( 89, 103,87,67,86,56)
select * from #test
--drop table #test
thanks in advance.
The easiest way to do this is just cross applying the min/max values of the columns. For example:
SELECT *
FROM #test t
CROSS APPLY (
SELECT MAX(val), MIN(val)
FROM (VALUES (t.column1), (t.column2), (t.column3), (t.column4), (t.column5), (t.column6)) AS c(val)
) AS c(maxvalue, minvalue);
Using the VALUES method to unpivot the data and then reaggravating it will make for a cleaner syntax but it does come with a cost to performance (not terrible but it is there). Using CASE expressions is a bit more cumbersome but in the syntax department, especially if there a lot of columns to be evaluated, but you won't incur the same performance penalty...
SELECT
t.column1, t.column2, t.column3, t.column4, t.column5, t.column6,
MinValue = CASE
WHEN t.column1 <= t.column2 AND t.column1 <= t.column3 AND t.column1 <= t.column4 AND t.column1 <= t.column5 AND t.column1 <= t.column6 THEN t.column1
WHEN t.column2 <= t.column1 AND t.column2 <= t.column3 AND t.column2 <= t.column4 AND t.column2 <= t.column5 AND t.column2 <= t.column6 THEN t.column2
WHEN t.column3 <= t.column1 AND t.column3 <= t.column2 AND t.column3 <= t.column4 AND t.column3 <= t.column5 AND t.column3 <= t.column6 THEN t.column3
WHEN t.column4 <= t.column1 AND t.column4 <= t.column2 AND t.column4 <= t.column3 AND t.column4 <= t.column5 AND t.column4 <= t.column6 THEN t.column4
WHEN t.column5 <= t.column1 AND t.column5 <= t.column2 AND t.column5 <= t.column3 AND t.column5 <= t.column4 AND t.column5 <= t.column6 THEN t.column5
ELSE t.column6
END,
MaxValue = CASE
WHEN t.column1 >= t.column2 AND t.column1 >= t.column3 AND t.column1 >= t.column4 AND t.column1 >= t.column5 AND t.column1 >= t.column6 THEN t.column1
WHEN t.column2 >= t.column1 AND t.column2 >= t.column3 AND t.column2 >= t.column4 AND t.column2 >= t.column5 AND t.column2 >= t.column6 THEN t.column2
WHEN t.column3 >= t.column1 AND t.column3 >= t.column2 AND t.column3 >= t.column4 AND t.column3 >= t.column5 AND t.column3 >= t.column6 THEN t.column3
WHEN t.column4 >= t.column1 AND t.column4 >= t.column2 AND t.column4 >= t.column3 AND t.column4 >= t.column5 AND t.column4 >= t.column6 THEN t.column4
WHEN t.column5 >= t.column1 AND t.column5 >= t.column2 AND t.column5 >= t.column3 AND t.column5 >= t.column4 AND t.column5 >= t.column6 THEN t.column5
ELSE t.column6
END
FROM
#test t;
Results...
column1 column2 column3 column4 column5 column6 MinValue MaxValue
----------- ----------- ----------- ----------- ----------- ----------- ----------- -----------
89 103 87 67 86 56 56 103
I found this solution here.
SELECT
column1
,column2
,column3
,column4
,column5
,column6
,(SELECT MAX(MaxValue)
FROM (VALUES (column1),(column2),(column3), (column4), (column5), (column6)) AS [Values](MaxValue))
AS MaxValue
,(SELECT MIN(MinValue)
FROM (VALUES (column1),(column2),(column3), (column4), (column5), (column6)) AS [Values](MinValue))
AS MinValue
FROM #test
i try to use case in for my condition to show out which is late,but after i use case when my result show out too many result.
select
grp.checktime,
--min(CONVERT(smalldatetime,l.checktime)) as clockin,
--max(CONVERT(smalldatetime,l.checktime)) as clockout,
ClockIn = case when min(cast(l.checktime as time)) <= cast(sc.StartTime as time)
then convert(varchar(100), cast(l.checktime as time), 100)
else 'Late ClockIn ' + convert(varchar(100), cast(l.checktime as time), 100)
end,
Clockout = case when max(cast(l.checktime as time)) >= cast(sc.EndTime as time)
then convert(varchar(100), cast(l.checktime as time), 100)
else 'Early ClockOut ' + convert(varchar(100), cast(l.checktime as time), 100)
end,
l.userid,
u.showname,
u.BADGENUMBER
from checkinout l
inner join userinfo u on l.userid = u.userid
inner join UserUsedsclasses uuc on u.userid = uuc.userid
inner join SchClass sc on uuc.SchId = sc.schClassid
inner join (
select distinct CONVERT(Date,checktime) as checktime
from checkinout
group by CONVERT(Date,checktime)
) as grp on grp.checktime = CONVERT(Date, l.checktime)
where uuc.SchId = 1 and u.badgenumber = 107
and u.badgenumber not in (79, 103, 78)
and l.checktime >= dateadd(month, datediff(month, 0, GETDATE() ) , 0)
and l.checktime < dateadd(month, datediff(month, 0, GETDATE ())+1, 0)
group by grp.checktime,l.userid,u.showname,u.BADGENUMBER,sc.StartTime,l.checktime,sc.EndTime
my result show me
Change your group by to group by the date of l.checktime.
select
grp.checktime,
--min(convert(smalldatetime,l.checktime)) as clockin,
--max(convert(smalldatetime,l.checktime)) as clockout,
ClockIn = case when min(cast(l.checktime as time)) <= cast(sc.StartTime as time)
then convert(varchar(100), cast(l.checktime as time), 100)
else 'Late ClockIn ' + convert(varchar(100), cast(l.checktime as time), 100)
end,
Clockout = case when max(cast(l.checktime as time)) >= cast(sc.EndTime as time)
then convert(varchar(100), cast(l.checktime as time), 100)
else 'Early ClockOut ' + convert(varchar(100), cast(l.checktime as time), 100)
end,
l.userid,
u.showname,
u.BADGENUMBER
from checkinout l
inner join userinfo u on l.userid = u.userid
inner join UserUsedsclasses uuc on u.userid = uuc.userid
inner join SchClass sc on uuc.SchId = sc.schClassid
inner join (
select distinct convert(Date,checktime) as checktime
from checkinout
group by convert(Date,checktime)
) as grp on grp.checktime = convert(Date, l.checktime)
where uuc.SchId = 1 and u.badgenumber = 107
and u.badgenumber not in (79, 103, 78)
and l.checktime >= dateadd(month, datediff(month, 0, getdate() ) , 0)
and l.checktime < dateadd(month, datediff(month, 0, getdate ())+1, 0)
group by
grp.checktime
, l.userid
, u.showname
, u.BADGENUMBER
, sc.StartTime
, convert(date, l.checktime)
, sc.EndTime
I have a nestled query I need to use in my CASE statement. I need to use the Max(AgeDate) that is correctly retrieved in the SELECT statement in my CASE statement but it does not see my Max(AgeDate) in my SELECT statement in my CASE statement. Please help...
Select
Inv.InvoiceNumber,
Fact_FinInvoice.InvoiceID,
dbo.Dim_Date.FullDate AS InvoiceDate,
pra.PracticeName,
pra.PracticeLogonName,
pat.AccNo,
pat.FileNo,
pmai.MedicalAidNumber,
per.Title + ' ' + per.Initials + ' ' + per.Surname AS PatientName,
sch.SCHEMES5,
sch.SchemeOption,
(SELECT MAX(B.AgeDate) FROM Fact_FinInvoice B WHERE Fact_FinInvoice.InvoiceID = B.InvoiceID AND Fact_FinInvoice.PracticeIdKey = B.PracticeIdKey) MaxAgeDate,
SUM(Fact_FinInvoice.Amount) AS Amount,
SUM(Fact_FinInvoice.AmountFunder) AS AmountFunder,
SUM(Fact_FinInvoice.AmountPatient) AS AmountPatient,
SUM(CASE WHEN DATEDIFF(dd, MaxAgeDate, GETDATE()) between 0 and 29 and AmountFunder != 0 THEN AmountFunder ELSE 0 END) as FunderCurrent,
SUM(CASE WHEN DATEDIFF(dd, MaxAgeDate, GETDATE()) between 30 and 59 and AmountFunder != 0 THEN AmountFunder ELSE 0 END) as Funder30Days,
SUM(CASE WHEN DATEDIFF(dd, MaxAgeDate, GETDATE()) between 60 and 89 and AmountFunder != 0 THEN AmountFunder ELSE 0 END) as Funder60Days,
SUM(CASE WHEN DATEDIFF(dd, MaxAgeDate, GETDATE()) between 90 and 119 and AmountFunder != 0 THEN AmountFunder ELSE 0 END) as Funder90Days,
SUM(CASE WHEN DATEDIFF(dd, MaxAgeDate, GETDATE()) >= 120 and AmountFunder != 0 THEN AmountFunder ELSE 0 END) as Funder120Days,
SUM(CASE WHEN DATEDIFF(dd, MaxAgeDate, GETDATE()) between 0 and 29 and AmountPatient != 0 THEN AmountPatient ELSE 0 END) as PatientCurrent,
SUM(CASE WHEN DATEDIFF(dd, MaxAgeDate, GETDATE()) between 30 and 59 and AmountPatient != 0 THEN AmountPatient ELSE 0 END) as Patient30Days,
SUM(CASE WHEN DATEDIFF(dd, MaxAgeDate, GETDATE()) between 60 and 89 and AmountPatient != 0 THEN AmountPatient ELSE 0 END) as Patient60Days,
SUM(CASE WHEN DATEDIFF(dd, MaxAgeDate, GETDATE()) between 90 and 119 and AmountPatient != 0 THEN AmountPatient ELSE 0 END) as Patient90Days,
SUM(CASE WHEN DATEDIFF(dd, MaxAgeDate, GETDATE()) >= 120 and AmountPatient != 0 THEN AmountPatient ELSE 0 END) as Patient120Days,
mcs.Name AS BureauManager,
mcso.Name AS BureauOfficer
FROM dbo.Fact_FinInvoice LEFT OUTER JOIN
dbo.Dim_Practice pra ON dbo.Fact_FinInvoice.PracticeIdKey = pra.PracticeIDCode LEFT OUTER JOIN
dbo.Fact_Invoice Inv ON dbo.Fact_FinInvoice.InvoiceID = Inv.ID LEFT OUTER JOIN
dbo.Dim_PersonMAInfo pmai INNER JOIN
dbo.Dim_Scheme sch ON sch.CodeNo = pmai.CodeNo ON Inv.PersonMAInfoCode = pmai.PersonMAInfoID LEFT OUTER JOIN
dbo.Dim_BureauStaffProvider bsp INNER JOIN
dbo.Dim_MediChargeStaff mcs ON mcs.ID = bsp.BureauStaffId ON bsp.ProviderID = Inv.ProviderId INNER JOIN
dbo.Dim_MediChargeStaff mcso ON mcs.Manager = mcso.ID LEFT OUTER JOIN
dbo.Dim_Date ON Inv.InvoiceDateKey = dbo.Dim_Date.DateKey LEFT OUTER JOIN
dbo.Dim_Patient pat INNER JOIN
dbo.Dim_PersonData per ON per.PersonDataId = pat.PersonId ON pat.PatientId = Inv.PatientKey
GROUP BY Inv.InvoiceNumber,
Fact_FinInvoice.InvoiceID,
dbo.Dim_Date.FullDate,
pra.PracticeName,
pra.PracticeLogonName,
pmai.MedicalAidNumber,
sch.SCHEMES5,
sch.SchemeOption,
mcs.Name,
mcso.Name,
pat.AccNo,
pat.FileNo,
per.Title + ' ' + per.Initials + ' ' + per.Surname,
[Fact_FinInvoice].PracticeIdKey
USE CTE on top and then join that CTE with your joins:
;with mycte as (
select MAX(AgeDate) as MaxAgeDate,InvoiceID FROM Fact_FinInvoice
group by InvoiceID
)
Select
Inv.InvoiceNumber,
Fact_FinInvoice.InvoiceID,
dbo.Dim_Date.FullDate AS InvoiceDate,
pra.PracticeName,
pra.PracticeLogonName,
pat.AccNo,
pat.FileNo,
pmai.MedicalAidNumber,
per.Title + ' ' + per.Initials + ' ' + per.Surname AS PatientName,
sch.SCHEMES5,
sch.SchemeOption,
MaxAgeDate,
SUM(Fact_FinInvoice.Amount) AS Amount,
SUM(Fact_FinInvoice.AmountFunder) AS AmountFunder,
SUM(Fact_FinInvoice.AmountPatient) AS AmountPatient,
SUM(CASE WHEN DATEDIFF(dd, MaxAgeDate, GETDATE()) between 0 and 29 and AmountFunder != 0 THEN AmountFunder ELSE 0 END) as FunderCurrent,
SUM(CASE WHEN DATEDIFF(dd, MaxAgeDate, GETDATE()) between 30 and 59 and AmountFunder != 0 THEN AmountFunder ELSE 0 END) as Funder30Days,
SUM(CASE WHEN DATEDIFF(dd, MaxAgeDate, GETDATE()) between 60 and 89 and AmountFunder != 0 THEN AmountFunder ELSE 0 END) as Funder60Days,
SUM(CASE WHEN DATEDIFF(dd, MaxAgeDate, GETDATE()) between 90 and 119 and AmountFunder != 0 THEN AmountFunder ELSE 0 END) as Funder90Days,
SUM(CASE WHEN DATEDIFF(dd, MaxAgeDate, GETDATE()) >= 120 and AmountFunder != 0 THEN AmountFunder ELSE 0 END) as Funder120Days,
SUM(CASE WHEN DATEDIFF(dd, MaxAgeDate, GETDATE()) between 0 and 29 and AmountPatient != 0 THEN AmountPatient ELSE 0 END) as PatientCurrent,
SUM(CASE WHEN DATEDIFF(dd, MaxAgeDate, GETDATE()) between 30 and 59 and AmountPatient != 0 THEN AmountPatient ELSE 0 END) as Patient30Days,
SUM(CASE WHEN DATEDIFF(dd, MaxAgeDate, GETDATE()) between 60 and 89 and AmountPatient != 0 THEN AmountPatient ELSE 0 END) as Patient60Days,
SUM(CASE WHEN DATEDIFF(dd, MaxAgeDate, GETDATE()) between 90 and 119 and AmountPatient != 0 THEN AmountPatient ELSE 0 END) as Patient90Days,
SUM(CASE WHEN DATEDIFF(dd, MaxAgeDate, GETDATE()) >= 120 and AmountPatient != 0 THEN AmountPatient ELSE 0 END) as Patient120Days,
mcs.Name AS BureauManager,
mcso.Name AS BureauOfficer
FROM dbo.Fact_FinInvoice LEFT OUTER JOIN
dbo.Dim_Practice pra ON dbo.Fact_FinInvoice.PracticeIdKey = pra.PracticeIDCode LEFT OUTER JOIN
dbo.Fact_Invoice Inv ON dbo.Fact_FinInvoice.InvoiceID = Inv.ID LEFT OUTER JOIN
dbo.Dim_PersonMAInfo pmai INNER JOIN
dbo.Dim_Scheme sch ON sch.CodeNo = pmai.CodeNo ON Inv.PersonMAInfoCode = pmai.PersonMAInfoID LEFT OUTER JOIN
dbo.Dim_BureauStaffProvider bsp INNER JOIN
dbo.Dim_MediChargeStaff mcs ON mcs.ID = bsp.BureauStaffId ON bsp.ProviderID = Inv.ProviderId INNER JOIN
dbo.Dim_MediChargeStaff mcso ON mcs.Manager = mcso.ID LEFT OUTER JOIN
dbo.Dim_Date ON Inv.InvoiceDateKey = dbo.Dim_Date.DateKey LEFT OUTER JOIN
dbo.Dim_Patient pat INNER JOIN
dbo.Dim_PersonData per ON per.PersonDataId = pat.PersonId ON pat.PatientId = Inv.PatientKey
join mycte ct
on Fact_FinInvoice.InvoiceID = ct.InvoiceID
GROUP BY Inv.InvoiceNumber,
Fact_FinInvoice.InvoiceID,
dbo.Dim_Date.FullDate,
pra.PracticeName,
pra.PracticeLogonName,
pmai.MedicalAidNumber,
sch.SCHEMES5,
sch.SchemeOption,
mcs.Name,
mcso.Name,
pat.AccNo,
pat.FileNo,
per.Title + ' ' + per.Initials + ' ' + per.Surname,
[Fact_FinInvoice].PracticeIdKey
You can't use aliases given in select part in other places in the select, but you can use outer apply to fetch data that you'll then use in select, with something like this:
select
....
sch.SchemeOption,
AD.MaxAgeDate,
....
SUM(CASE WHEN DATEDIFF(dd, AD.MaxAgeDate, GETDATE())
from
dbo.Fact_FinInvoice
outer apply (
SELECT MAX(B.AgeDate)
FROM Fact_FinInvoice B
WHERE Fact_FinInvoice.InvoiceID = B.InvoiceID AND
Fact_FinInvoice.PracticeIdKey = B.PracticeIdKey) AD
LEFT OUTER JOIN ...
And you can also calculate the datediff already in the outer apply as a second column, so you don't have to repeat the same code several times.
Use Cross Apply
SELECT Inv.InvoiceNumber,
Fact_FinInvoice.InvoiceID,
dbo.Dim_Date.FullDate AS InvoiceDate,
pra.PracticeName,
pra.PracticeLogonName,
pat.AccNo,
pat.FileNo,
pmai.MedicalAidNumber,
per.Title + ' ' + per.Initials + ' ' + per.Surname AS PatientName,
sch.SCHEMES5,
sch.SchemeOption,
cs.MaxAgeDate,
Sum(Fact_FinInvoice.Amount) AS Amount,
Sum(Fact_FinInvoice.AmountFunder) AS AmountFunder,
Sum(Fact_FinInvoice.AmountPatient) AS AmountPatient,
Sum(CASE
WHEN Datediff(dd, MaxAgeDate, Getdate()) BETWEEN 0 AND 29
AND AmountFunder != 0 THEN AmountFunder
ELSE 0
END) AS FunderCurrent,
Sum(CASE
WHEN Datediff(dd, MaxAgeDate, Getdate()) BETWEEN 30 AND 59
AND AmountFunder != 0 THEN AmountFunder
ELSE 0
END) AS Funder30Days,
Sum(CASE
WHEN Datediff(dd, MaxAgeDate, Getdate()) BETWEEN 60 AND 89
AND AmountFunder != 0 THEN AmountFunder
ELSE 0
END) AS Funder60Days,
Sum(CASE
WHEN Datediff(dd, MaxAgeDate, Getdate()) BETWEEN 90 AND 119
AND AmountFunder != 0 THEN AmountFunder
ELSE 0
END) AS Funder90Days,
Sum(CASE
WHEN Datediff(dd, MaxAgeDate, Getdate()) >= 120
AND AmountFunder != 0 THEN AmountFunder
ELSE 0
END) AS Funder120Days,
Sum(CASE
WHEN Datediff(dd, MaxAgeDate, Getdate()) BETWEEN 0 AND 29
AND AmountPatient != 0 THEN AmountPatient
ELSE 0
END) AS PatientCurrent,
Sum(CASE
WHEN Datediff(dd, MaxAgeDate, Getdate()) BETWEEN 30 AND 59
AND AmountPatient != 0 THEN AmountPatient
ELSE 0
END) AS Patient30Days,
Sum(CASE
WHEN Datediff(dd, MaxAgeDate, Getdate()) BETWEEN 60 AND 89
AND AmountPatient != 0 THEN AmountPatient
ELSE 0
END) AS Patient60Days,
Sum(CASE
WHEN Datediff(dd, MaxAgeDate, Getdate()) BETWEEN 90 AND 119
AND AmountPatient != 0 THEN AmountPatient
ELSE 0
END) AS Patient90Days,
Sum(CASE
WHEN Datediff(dd, MaxAgeDate, Getdate()) >= 120
AND AmountPatient != 0 THEN AmountPatient
ELSE 0
END) AS Patient120Days,
mcs.Name AS BureauManager,
mcso.Name AS BureauOfficer
FROM dbo.Fact_FinInvoice FFI
LEFT OUTER JOIN dbo.Dim_Practice pra ON FFI.PracticeIdKey = pra.PracticeIDCode
LEFT OUTER JOIN dbo.Fact_Invoice Inv ON FFI.InvoiceID = Inv.ID
LEFT OUTER JOIN dbo.Dim_PersonMAInfo pmai
INNER JOIN dbo.Dim_Scheme sch ON sch.CodeNo = pmai.CodeNo ON Inv.PersonMAInfoCode = pmai.PersonMAInfoID
LEFT OUTER JOIN dbo.Dim_BureauStaffProvider bsp
INNER JOIN dbo.Dim_MediChargeStaff mcs ON mcs.ID = bsp.BureauStaffId ON bsp.ProviderID = Inv.ProviderId
INNER JOIN dbo.Dim_MediChargeStaff mcso ON mcs.Manager = mcso.ID
LEFT OUTER JOIN dbo.Dim_Date ON Inv.InvoiceDateKey = dbo.Dim_Date.DateKey
LEFT OUTER JOIN dbo.Dim_Patient pat
INNER JOIN dbo.Dim_PersonData per ON per.PersonDataId = pat.PersonId ON pat.PatientId = Inv.PatientKey
CROSS APPLY (SELECT Max(B.AgeDate) AS MaxAgeDAte
FROM Fact_FinInvoice B
WHERE FFI.InvoiceID = B.InvoiceID
AND FFI.PracticeIdKey = B.PracticeIdKey) CS
GROUP BY Inv.InvoiceNumber,
FFI.InvoiceID,
dbo.Dim_Date.FullDate,
pra.PracticeName,
pra.PracticeLogonName,
pmai.MedicalAidNumber,
sch.SCHEMES5,
sch.SchemeOption,
mcs.Name,
mcso.Name,
pat.AccNo,
pat.FileNo,
per.Title + ' ' + per.Initials + ' ' + per.Surname,
[FFI].PracticeIdKey