Calculate difference between two columns sql - sql

in my SQL Query i am Calculating column values by using CASE WHEN THEN ELSE END Condition.
Now i want to find difference between computed column and normal column
My Query
SELECT T.Ticket [Ticket],
TT.TicketType [Ticket Type],
T.Dependency [Dependency],
CASE
WHEN (
SELECT TOP 1 f1.UpdatedOn
FROM TicketTypeFollowUp AS f1
WHERE f1.UpdatedOn < T.UpdatedOn
AND f1.Ticket = 61423
ORDER BY f1.UpdatedOn DESC
) IS NULL
THEN Ticket.TicketRaisedOn
ELSE (
SELECT TOP 1 f1.UpdatedOn
FROM TicketTypeFollowUp AS f1
WHERE f1.UpdatedOn < T.UpdatedOn
AND f1.Ticket = 61423
ORDER BY f1.UpdatedOn DESC
)
END [Start Date],
T.UpdatedOn [End Date],
L.EmpName [Updated By]
FROM dbo.TicketTypeFollowUp T
LEFT JOIN dbo.Ticket
ON T.Ticket = Ticket.Code
LEFT JOIN dbo.TicketType TT
ON T.TicketType = TT.Code
LEFT JOIN LoginUser L
ON T.UpdatedBy = L.Code
WHERE Ticket = 61423
Query Result
Ticket Type Dependency Start Date End Date Updated By
61423 FLM AGS 2013-01-22 15:50:08.757 2013-01-22 18:35:50.893 Kedar S
I want one more column which displays End Time - Start Time I have used CASE hence i am unable to compute difference.
Database is SQL SERVER 2008

with lastUpdate(ticket, lastUpdate) as (
select ticket,
max(updateOn)
from TicketTypeFollowUp
group by ticket)
SELECT T.Ticket [Ticket],
TT.TicketType [Ticket Type],
T.Dependency [Dependency],
coalesce(lastUpdate, ticketRaisedOn) [Start Date],
T.UpdatedOn [End Date],
datediff(mi, coalesce(lastUpdate, ticketRaisedOn), T.UpdatedOn) durationMins,
L.EmpName [Updated By]
FROM dbo.TicketTypeFollowUp T
LEFT JOIN dbo.Ticket
ON T.Ticket = Ticket.Code
LEFT JOIN dbo.TicketType TT
ON T.TicketType = TT.Code
LEFT JOIN LoginUser L
ON T.UpdatedBy = L.Code
left join lastUpdate lu on t.ticket = lu.ticket
WHERE Ticket = 61423

You can use your current query as a CTE or a derived table. Here is an example using a CTE:
;WITH CTE AS
(
-- your current query here
)
SELECT *, DATEDIFF(MINUTE,[Start Date],[End Date]) [End Time - Start Time]
FROM CTE

Related

Pivoting to append the last 6 payments for 24 loans

I am building a query in Microsoft sql server where I want to find the active loans as well as some information on them. I have built out a common table expression that gives me the correct population. Now I need to get the last 6 payments starting from today. I have a another common table expression that gives all the payments and the payment data received but I am not sure how to pivot and append the last 6 payments such that I have something like this:
This is what the query and output looks like for the common table expression where I can get c1,...,c6.
SELECT Account,Total,CONVERT(datetime,DateRec) [Date Received]
FROM mars.dbo.vw_PaymentHistory PH
WHERE PH.SourceTyp not like '%fundin%' and PH.SourceTyp not like '%draw%'
which gives this (but much more):
Here is the whole query I am working from:
Declare #monthEnding date = '3/31/2020',
#monthStart date = '3/1/2020';
WITH Active_Loans as (
SELECT
la.Account,
la.LoanStatus,
la.PrinBal,
isnull(b.Amount, 0) [DUPB],
la.PrinBal + isnull(b.Amount, 0) [TotalUPB],
l.NoteOwner,
pt.[Partition],
l.paidoffdate,
la.[First Name],
la.[Last Name],
la.PmtPI,
la.PmtImpound,
la.NextDueDate,
la.MaturityDate,
la.NoteOwner as [Note Owner]
FROM MARS_DW..vw_vw_Loans_ArchiveEOM la
LEFT JOIN MARS_DW..vw_DUPBByLoan b on b.Account = la.Account
AND b.ArchiveDate = la.ArchiveDate
LEFT JOIN MARS..vw_Loans l on l.Account = la.Account
LEFT JOIN Portfolio_Analytics..partition_table pt on pt.Noteowner = l.NoteOwner
WHERE la.MonthEnding = #monthEnding
AND la.isActive = 1
AND la.PaidOffDate is null
AND la.LoanStatus NOT LIKE 'BK Payment Plan'
AND la.LoanStatus NOT LIKE 'Prelim'
AND la.LoanStatus NOT like 'trailing claims'
AND la.Account NOT IN (
SELECT account
FROM MARS..vw_Loans
WHERE servicexferdate <=
DATEADD(dd, - 1, DATEADD(mm, DATEDIFF(mm, 0, #monthStart) + 1, 0))
AND PaidOffDate BETWEEN #monthStart AND DATEADD(dd, - 1, DATEADD(mm, DATEDIFF(mm, 0, #monthStart) + 1, 0))
)
UNION
(
SELECT l.account
,la.LoanStatus
,la.PrinBal
,isnull(b.Amount, 0) [DUPB]
,la.PrinBal + isnull(b.Amount, 0) [TotalUPB]
,l.NoteOwner
,pt.[Partition]
,l.PaidOffDate
,la.[First Name]
,la.[Last Name]
,la.PmtPI
,la.PmtImpound
,la.NextDueDate
,la.MaturityDate
,la.NoteOwner as [Note Owner]
FROM MARS..vw_Loans l
LEFT JOIN MARS_DW..vw_vw_Loans_ArchiveEOM la on la.Account = l.Account
LEFT JOIN MARS_DW..vw_DUPBByLoan b on b.Account = la.Account
LEFT JOIN Portfolio_Analytics..partition_table pt on pt.Noteowner = l.NoteOwner
AND b.ArchiveDate = la.ArchiveDate
WHERE l.servicexferdate < #monthEnding
AND l.PaidOffDate > #monthEnding
AND la.MonthEnding = #monthEnding
AND la.LoanStatus NOT like 'trailing claims'
AND la.LoanStatus NOT like 'Inactive - REO/FC'
AND pt.[Partition] IS NOT NULL
)
)
,
payments as
(
SELECT Account,Total,CONVERT(datetime,DateRec) [Date Received]
FROM mars.dbo.vw_PaymentHistory PH
WHERE PH.SourceTyp not like '%fundin%' and PH.SourceTyp not like '%draw%'
)
SELECT
rptpop.Account
, rptpop.[First Name]
, rptpop.[Last Name]
, '$' + CONVERT (VARCHAR (12), rptpop.PmtPI+rptpop.PmtImpound, 1) as PITI
,'$' + CONVERT (VARCHAR (12), rptpop.TotalUPB, 1) as [Total UPB]
, CONVERT(VARCHAR(10),rptpop.NextDueDate,101) as [Next Due Date]
, CONVERT(VARCHAR(10),rptpop.MaturityDate,101) as [Maturity Date]
, rptpop.[Note Owner]
FROM Active_Loans as rptpop
LEFT JOIN payments as pmt on pmt.Account = rptpop.Account
WHERE
rptpop.Partition = 'GAEA'
AND rptpop.LoanStatus = 'Current'
AND rptpop.[Last Name] NOT LIKE '%CRE%'
AND pmt.[Date Received] BETWEEN #monthStart AND #monthEnding
EDIT:
Based on the answer below I was able to do this:
payments as
(
SELECT ROW_NUMBER() OVER(Partition By Account ORDER BY CONVERT(datetime,DateRec) DESC) AS [RowNumber], Total, Account
FROM mars.dbo.vw_PaymentHistory
)
,
get_payment1 as
(
SELECT * FROM payments
where RowNumber = 1
)
Which gives me numbers but what I do not understand is whether 1.) This is indeed correct and 2.) Assuming it is correct how do is it getting the most recent date? Perhaps its the order by clause?
I see a couple of way to solve the problem. I can share the approach using pseudo code.
Create Payments CTE , something like SELECT ROW_NUMBER() OVER(Partition By Account ORDER BY ReceivedDate DESC) . Then create 6 CTE's that use the above CTE with Row_Number 1 thru 6. Then simply use those using Left Join in your query, joining on Account#. This will add c1-c6 columns.
A second approach can be to use the same Payments CTE but instead of multiple CTEs, find a way to use UNPIVOT unpivot (Amount for Rows in (1,2,3,4,5,6) ) u;

How do I list the count of occurrences using the over() function, but only display the occurrences that are listed in the result 3 or more times?

How do I list the amount of times each account number has occurred if I only want to see the ones that have occurred 3 times or more?
I'm using a window OVER() function to get the number of times the account number is listed.
SELECT a.ACCOUNTNUMBER AS [Account Number]
, CONCAT(n.FIRST, ' ', n.MIDDLE, ' ', n.LAST) AS [Member Name]
, l.id AS [Loan ID]
, COUNT(a.ACCOUNTNUMBER)
OVER(partition by a.ACCOUNTNUMBER) as [Number of
Tracking Record]
, n.EMAIL AS [Email]
, n.HOMEPHONE AS [Phone Number]
FROM dbo.account a
INNER JOIN dbo.LOAN l
ON a.ACCOUNTNUMBER = l.PARENTACCOUNT
INNER JOIN dbo.LOANTRACKING lt
ON l.PARENTACCOUNT = lt.PARENTACCOUNT
AND l.ID = lt.ID
INNER JOIN dbo.NAME n
ON a.ACCOUNTNUMBER = n.PARENTACCOUNT
WHERE lt.type = 46
AND l.ProcessDate = CONVERT(VARCHAR(8), dateadd(day,-1, getdate()),
112)
AND lt.ProcessDate = CONVERT(VARCHAR(8), dateadd(day,-1, getdate()),
112)
AND a.CLOSEDATE IS NULL
AND lt.EXPIREDATE IS NULL
GROUP BY a.ACCOUNTNUMBER, n.FIRST, n.MIDDLE, n.LAST, l.id, n.email,
n.HOMEPHONE
ORDER BY [Account Number]
Right now my result is giving me the number of times all of the accounts are listed in the "Number of Tracking Record" column. I want to see only the account numbers that have "3" occurrences or above.
My current result:
My Desired Result:
SELECT * -- edit to include only your relevant columnns
FROM
(
SELECT a.ACCOUNTNUMBER AS [Account Number]
, CONCAT(n.FIRST, ' ', n.MIDDLE, ' ', n.LAST) AS [Member Name]
, l.id AS [Loan ID]
, COUNT(a.ACCOUNTNUMBER)
OVER(partition by a.ACCOUNTNUMBER) as [Number of
Tracking Record]
, n.EMAIL AS [Email]
, n.HOMEPHONE AS [Phone Number]
FROM dbo.account a
INNER JOIN dbo.LOAN l
ON a.ACCOUNTNUMBER = l.PARENTACCOUNT
INNER JOIN dbo.LOANTRACKING lt
ON l.PARENTACCOUNT = lt.PARENTACCOUNT
AND l.ID = lt.ID
INNER JOIN dbo.NAME n
ON a.ACCOUNTNUMBER = n.PARENTACCOUNT
WHERE lt.type = 46
AND l.ProcessDate = CONVERT(VARCHAR(8), dateadd(day,-1, getdate()),
112)
AND lt.ProcessDate = CONVERT(VARCHAR(8), dateadd(day,-1, getdate()),
112)
AND a.CLOSEDATE IS NULL
AND lt.EXPIREDATE IS NULL
GROUP BY a.ACCOUNTNUMBER, n.FIRST, n.MIDDLE, n.LAST, l.id, n.email,
n.HOMEPHONE
) MyQuery
WHERE MyQuery.[Number of Tracking Record] >= 3
ORDER BY [Account Number]
I added an "outer" query around yours, using yours as a subquery, and filtered it for those with just the >=3 condition. And I moved the ORDER BY from your inside query to the outer query, as it's just used for ordering the results and not used in the computation itself.

Query displays incorrect ordering

The output that is needed is attached as an image. The code I currently have displays Arrival Date and Departure Date correctly, but the Guest names displayed are not exactly the same as the image. The image displays first names in a random order while the last names are ordered correctly.
SELECT UPPER(substring(GLASTNAME,1,1)) + LOWER(SUBSTRING(GLASTNAME,2,len(GLASTNAME)-1)) + ', '+
UPPER(substring(GFIRSTNAME,1,1)) + LOWER(SUBSTRING(GFIRSTNAME,2,len(GFIRSTNAME)-1)) AS Guest,
FORMAT(ARRIVAL_DATE, 'dddd MM/dd/yy') AS [Arrival Date],
FORMAT(DateADD(d,NUMDAYS, ARRIVAL_DATE),'dddd MM/dd/yy') AS [Departure Date]
FROM guestWH g INNER JOIN reservationWH r ON g.RNUM = r.RNUM
INNER JOIN packageWH p ON r.P_ID = p.P_ID
WHERE NUMDAYS = 5 OR NUMDAYS = 6 OR NUMDAYS = 7
ORDER BY [Arrival Date] ASC
Correct answer
My current output looks like this: https://imgur.com/i3wqvQM
You need to order by guest and then [Arrival Date] - so you can try below using 1 which means it will order by first column which is guestname in your case and then [Arrival Date]
SELECT UPPER(substring(GLASTNAME,1,1)) + LOWER(SUBSTRING(GLASTNAME,2,len(GLASTNAME)-1)) + ', '+
UPPER(substring(GFIRSTNAME,1,1)) + LOWER(SUBSTRING(GFIRSTNAME,2,len(GFIRSTNAME)-1)) AS Guest,
FORMAT(ARRIVAL_DATE, 'dddd MM/dd/yy') AS [Arrival Date],
FORMAT(DateADD(d,NUMDAYS, ARRIVAL_DATE),'dddd MM/dd/yy') AS [Departure Date]
FROM guestWH g INNER JOIN reservationWH r ON g.RNUM = r.RNUM
INNER JOIN packageWH p ON r.P_ID = p.P_ID
WHERE NUMDAYS = 5 OR NUMDAYS = 6 OR NUMDAYS = 7
ORDER BY 1, [Arrival Date] ASC

SQL query multiplying SUM results when joining to multiple transaction tables

I'm developing a report which measures cash performance based on allocation and cancellation dates. To measure this I've queried a transactions sub query which pulls back all transactions and is joined on an account number and transaction from and to dates. This is then summed up at the top of the query.
All works fine when using one sub query however I'm now having to add an extra transactions sub query; 1 to calculate actual payments from the allocation date (to cancellation date or today if value is null) and the 2nd to calculate any cancelled payments from the allocation date + 14 days (to cancellation date or today if value is null).
The first sub query works perfectly but now I've added the second it's multiplying the summed value by 8. I've had this in the past when trying to query this table twice. (Not always by 8). Any ideas?
Thanks
The sums totalling these (TEST1 works fine, TEST2 not so much) and the sub queries:
SUM(CASE WHEN v1.[Transaction Date1] >= dateadd(DD, 1, EOMONTH(getdate(), -1))
THEN v1.[Payments] ELSE 0
END) AS TEST1,
SUM(CASE WHEN v2.[Transaction Date2] >= dateadd(DD, 1, EOMONTH(getdate(), -1))
THEN v2.[Payments2] ELSE 0
END) AS TEST2,
My code:
LEFT JOIN
(SELECT
[Account Number1], [Transaction Date1], SUM([Payments1]) AS [Payments]
FROM
(SELECT
ACCOUNTNO AS [Account Number1],
TRANDT AS [Transaction Date1],
CASE
WHEN TRANSACTIONTYPE = 'Credit'
THEN TRANAMT * -1
ELSE TRANAMT
END [Payments1]
FROM
TRANSACTIONS t WITH (NOLOCK)
JOIN
TRANSACTIONDETAILS td WITH (NOLOCK) ON td.TRANSACTIONID = t.TRANSACTIONS1
JOIN
TRANSACTIONS a WITH (NOLOCK) ON a.ID = TRANSACTIONS1
AND [TRANTYPE] LIKE '%PAY%'
AND [TRANAMT] <> 0
INNER JOIN
ACCOUNTS na WITH (NOLOCK) ON a.ACCOUNTID = ACCOUNTS1
WHERE
TRANSACTIONTYPE = 'Credit') v
GROUP BY
[Account Number1], [Transaction Date1]) v1 ON MAINT.[ACCNO] = v1.[Account Number1]
AND MAINT.[Allocation Date] <= v1.[Transaction Date1]
AND v1.[Transaction Date1] <= MAINT.[Transaction to date]
LEFT JOIN
(SELECT
[Account Number2], [Transaction Date2], SUM([Payments2]) AS [Payments2]
FROM
(SELECT
ACCOUNTNO AS [Account Number2],
TRANDT AS [Transaction Date2],
CASE
WHEN TRANSACTIONTYPE = 'Credit'
THEN TRANAMT * -1
ELSE TRANAMT
END [Payments2]
FROM
TRANSACTIONS t WITH (NOLOCK)
INNER JOIN
TRANSACTIONDETAILS td WITH (NOLOCK) ON td.TRANSACTIONID = t.TRANSACTIONS1
INNER JOIN
TRANSACTIONS a WITH (NOLOCK) ON a.ID = TRANSACTIONS1
AND [TRANTYPE] LIKE '%PAY%'
AND [TRANAMT] <> 0
INNER JOIN
ACCOUNTS na WITH (NOLOCK) ON a.ACCOUNTID = ACCOUNTS1
WHERE
TRANSACTIONTYPE = 'Debit') v
GROUP BY
[Account Number2], [Transaction Date2]) v2 ON MAINT.[ACCNO] = v2.[Account Number2]
AND DATEADD(DD,10,MAINT.[DCA Allocation Date]) <= v2.[Transaction Date2]
AND v2.[Transaction Date2] <= MAINT.[Transaction to date]
Since the inner most subselect is the same in both joins, you should put it in a WITH statement at the top and then just use that twice.
Like this:
WITH v_CTE
AS
(SELECT
ACCOUNTNO AS [Account Number2],
TRANDT AS [Transaction Date2],
CASE
WHEN TRANSACTIONTYPE = 'Credit'
THEN TRANAMT * -1
ELSE TRANAMT
END [Payments2]
FROM
TRANSACTIONS t WITH (NOLOCK)
INNER JOIN
TRANSACTIONDETAILS td WITH (NOLOCK) ON td.TRANSACTIONID = t.TRANSACTIONS1
INNER JOIN
TRANSACTIONS a WITH (NOLOCK) ON a.ID = TRANSACTIONS1
AND [TRANTYPE] LIKE '%PAY%'
AND [TRANAMT] <> 0
INNER JOIN
ACCOUNTS na WITH (NOLOCK) ON a.ACCOUNTID = ACCOUNTS1
WHERE
TRANSACTIONTYPE = 'Debit')
...
LEFT JOIN
(SELECT
[Account Number1], [Transaction Date1], SUM([Payments1]) AS [Payments]
FROM
v_CTE v
GROUP BY
[Account Number1], [Transaction Date1]) v1 ON MAINT.[ACCNO] = v1.[Account Number1]
AND MAINT.[Allocation Date] <= v1.[Transaction Date1]
AND v1.[Transaction Date1] <= MAINT.[Transaction to date]
LEFT JOIN
(SELECT
[Account Number2], [Transaction Date2], SUM([Payments2]) AS [Payments2]
FROM
v_CTE v
GROUP BY
[Account Number2], [Transaction Date2]) v2 ON MAINT.[ACCNO] = v2.[Account Number2]
AND DATEADD(DD,10,MAINT.[DCA Allocation Date]) <= v2.[Transaction Date2]
AND v2.[Transaction Date2] <= MAINT.[Transaction to date]

Summing row before in a condition (SQL)

I have a spreadsheet where sales data is interspersed with other data in columns. The column headings for S always end with the sum between I(row before)+P(current row) - I(Current row). I would like the data to sum for each row only. I need to do this with SQL queries.
for example :
if the week is 201520, it will return 'X',
but if it isn't week 201520, then S(Column) = I(week 201547) + P(week 201548) - I(Week 201548)
Currently my queries is like this, but I don't get the logic in query for this case, can anybody help me?
select c.[SHIP TO CODE],Area,[Dealer/Account],
c.[PRODUCT CODE],c.Model,c.Category,c.WEEK,c.I,c.P,c.S
from(select distinct b.[SHIP TO CODE],rp.Model,rp.Category,b.[PRODUCT CODE],b.WEEK,b.QTY,
case when TYPE = 'I' then 'I' end as I,
case when TYPE = 'P' then 'P' end as P,
case when WEEK = '201550' then 'X' end as S from
(
select [SHIP TO CODE],[PRODUCT CODE],WEEK,qty,TYPE from Rekap
a
union
select [Ship-to party],Material,[Week-Ok],[1st G/I Qty],category from
SOT left join
SDate on [Tgl SAP] = [1st G/I Date]
)b
left join [Ref Prod]rp
on b.[PRODUCT CODE] = rp.ProductID
where WEEK is not null
)
c
left join [Ref Dealer]rd
on c.[SHIP TO CODE] = rd.[Ship To Code]
order by [Ship To Code],WEEK ASC
select * into #a from (
select
case when abcd.WEEK = '201520' then 'X' end as S,*
from(select abc.Area,abc.Channel,abc.[Dealer/Account],abc.[PRODUCT CODE],rp.Model,rp.Category,abc.week,abc.I,abc.P
from (select ab.[SHIP TO CODE],rd.Area,rd.Channel,rd.[Dealer/Account],ab.[PRODUCT CODE],
ab.WEEK,case when TYPE = 'I' then isnull(QTY,0) end as I,
case when TYPE = 'P' then isnull(qty,0) end as P
from(
select [SHIP TO CODE],[PRODUCT CODE],WEEK,qty,TYPE from Rekap
a
union all
select [Ship-to party],Material,[Week-Ok],[1st G/I Qty],category from
SOT left join
SDate on [Tgl SAP] = [Billing Date])
ab
left join [Ref Dealer]rd
on ab.[SHIP TO CODE] = rd.[Ship To Code]
)abc
left join
[Ref Prod]rp on rp.ProductID = abc.[PRODUCT CODE]
)abcd
--order by abcd.[Dealer/Account],abcd.WEEK
) a
select Area, Channel, [Dealer/Account], [Product Code], model, category, week,
CASE WHEN I IS NULL THEN 'P' WHEN P IS NULL THEN 'I' END type,
SUM(ISNULL(I,0)+ISNULL(p,0)) amount
into #b
from #a
where week is not null
group by area, channel,[dealer/account], [product code], model, category, week,
CASE WHEN I IS NULL THEN 'P' WHEN P IS NULL THEN 'I' END
order by week
--Grouping all, put into temp table
select Area, Channel, [Dealer/Account], [Product Code], model, category, week,
SUM(ISNULL(I,0)) I, SUM(ISNULL(p,0)) p
into #c
from #a
where week is not null
group by area, channel,[dealer/account], [product code], model, category, week
order by week
select *,(select MAX(week) from #c where a.week>#c.week
--IF NOT NEEDED
--and
--a.area=#c.area and a.channel=#c.channel and a.[dealer/account]=#c.[dealer/account] and a.[product code]=#c.[product code]
--and a.model=#c.model and a.category=#c.category
-- END OF
) lastweek
into #d
from #c a
select a.*, a.P-a.I+b.I s from #d a left join #d b on
a.area=b.area and a.channel=b.channel and a.[dealer/account]=b.[dealer/account] and a.[product code]=b.[product code]
and a.model=b.model and a.category=b.category and
a.lastweek=b.week
order by area, channel,[dealer/account], [product code], model, category, week