SQL Server Check if Value repeats in next row - sql

I need to check if the row value repeats in next row. If it does than the Ticket is still open and if it is closed then I need to show value in Closed column.
In example below, Ticket 55 is open from May 1st to May 7th so each day I am showing it Open in Open Column and on May 7th the Ticket is closed so I show it as closed
Ticket Open Closed
5/1/2019 55 1
5/2/2019 55 1
5/3/2019 55 1
5/4/2019 55 1
5/5/2019 55 1
5/6/2019 55 1
5/7/2019 55 1 1
5/8/2019 60

Assuming that ticket and he date column you showed no name for aren't nullable, you can use lead() to get the next ticket ID for a ticket where the records are ordered by the date column you showed no name for. If that is null that means there is no follow up. Also using lead() you can check if the date of the next record is the next day.
SELECT ...
CASE
WHEN lead(ticket) OVER (PARTITION BY ticket
ORDER BY <your anonymous date column>) IS NULL
OR lead(<your anonymous date column>) OVER (PARTITION BY ticket
ORDER BY <your anonymous date column>) <> dateadd(day, 1, <your anonymous date column>) THEN
1
END closed,
...
Replace <your anonymous date column> with the name of the date column.

Is this what you want?
select t.*,
(case when date = max(date) over (partition by ticket)
then 1 else 0
end) as closed
from t;
It would appear that you simply want 1 as open.
If the ticket values can repeat, use lead():
select t.*,
(case when ticket = lead(ticket) over (partition by ticket order by ticket)
then 0 else 1
end) as closed
from t;

If you use SQL Server 2012 or later you can use LEAD(). Here is a sample :
I have found next ticket number via LEAD() function partitioned by TicketNumber. If it returns a value that's mean the ticket still not closed. If it is null ticket is closed.
SELECT T.TicketDate
, T.TicketNumber
, CASE WHEN LEAD(T.TicketNumber) OVER (PARTITION BY T.TicketNumber ORDER BY T.TicketDate ) IS NULL THEN '' ELSE '1' END [Open]
, CASE WHEN LEAD(T.TicketNumber) OVER (PARTITION BY T.TicketNumber ORDER BY T.TicketDate ) IS NULL THEN '1'ELSE '' END Closed
FROM Ticket T

Related

SQL Divide previous row balance by current row balance and insert that value into current rows column "Growth"

I have a table where like this.
Year
ProcessDate
Month
Balance
RowNum
Calculation
2022
20220430
4
22855547
1
2022
20220330
3
22644455
2
2022
20220230
2
22588666
3
2022
20220130
1
33545444
4
2022
20221230
12
22466666
5
I need to take the previous row of each column and divide that amount by the current row.
Ex: Row 1 calculation should = Row 2 Balance / Row 1 Balance (22644455/22855547 = .99% )
Row 2 calculation should = Row 3 Balance / Row 2 Balance etc....
Table is just a Temporary table I created titled #MonthlyLoanBalance2.
Now I just need to take it a step further.
Let me know what and how you would go about doing this.
Thank you in advance!
Insert into #MonthlytLoanBalance2 (
Year
,ProcessDate
,Month
,Balance
,RowNum
)
select
--CloseYearMonth,
left(ProcessDate,4) as 'Year',
ProcessDate,
--x.LOANTypeKey,
SUBSTRING(CAST(x.ProcessDate as varchar(38)),5,2) as 'Month',
sum(x.currentBalance) as Balance
,ROW_NUMBER()over (order by ProcessDate desc) as RowNum
from
(
select
distinct LoanServiceKey,
LoanTypeKey,
AccountNumber,
CurrentBalance,
OpenDateKey,
CloseDateKey,
ProcessDate
from
cu.LAFactLoanSnapShot
where LoanStatus = 'Open'
and LoanTypeKey = 0
and ProcessDate in (select DateKey from dimDate
where IsLastDayOfMonth = 'Y'
and DateKey > convert(varchar, getdate()-4000, 112)
)
) x
group by ProcessDate
order by ProcessDate desc;``
I am assuming your data is already prepared as shown in the table. Now you can try Lead() function to resolve your issue. Remember format() function is used for taking only two precision.
SELECT *,
FORMAT((ISNULL(LEAD(Balance,1) OVER (ORDER BY RowNum), 1)/Balance),'N2') Calculation
FROM #MonthlytLoanBalance2

Calculating a value in SQL using previous row's values and current row value

I am trying to recreate the following in SQL where value at date of transaction needs to be calculated and value from other columns can be queried directly. It needs to add current value and transaction for first row of each type to get the value for 'value at date of transaction' and then for subsequent rows of that type, it needs to add 'value at date of transaction' from previous row to the 'transaction' value to get 'value at date of transaction' for current row. This process needs to start over for each type. Is this possible to recreate in SQL Server?
Type
Current Value
Transaction
Date of transaction
Value at date of transaction
A
5
2
12/31/2001
7
A
5
-3
12/30/2001
4
A
5
-1
12/29/2001
3
A
5
6
12/28/2001
9
B
100
20
12/31/2001
120
B
100
-50
12/30/2001
70
B
100
-10
12/29/2001
60
B
100
30
12/28/2001
90
C
20
7
12/31/2001
27
C
20
-3
12/30/2001
24
The structure seems odd to me.
But you can use the window function sum() over()
Declare #YourTable Table ([Type] varchar(50),[Current Value] int,[Transaction] int,[Date of transaction] date)
Insert Into #YourTable Values
('A',5,2,'12/31/2001')
,('A',5,-3,'12/30/2001')
,('A',5,-1,'12/29/2001')
,('A',5,6,'12/28/2001')
,('B',100,20,'12/31/2001')
,('B',100,-50,'12/30/2001')
,('B',100,-10,'12/29/2001')
,('B',100,30,'12/28/2001')
,('C',20,7,'12/31/2001')
,('C',20,-3,'12/30/2001')
Select *
,[Value at date] = [Current Value]
+ sum([Transaction]) over (partition by [Type] order by [Date of transaction] desc)
from #YourTable
Results
;with cte1
as (SELECT *,
/* conditional ROW_NUMBER to get the maxDate by Type and get only the Transaction Value+ immediately succeding row's Current Value*/
CASE
WHEN ROW_NUMBER() OVER (PARTITION BY Type ORDER BY Date_of_transaction DESC) = 1 then
LAG(Current_Value) OVER (PARTITION BY Type ORDER BY Date_of_transaction) + [Transaction]
else
[Transaction]
end as Base
FROM [Global_capturis_owner].[Book2]
)
select Type,
Current_Value,
[Transaction],
Date_of_transaction,
/* Windowed function to compute the Running Total*/
SUM(Base) OVER (PARTITION BY Type ORDER BY Date_of_transaction DESC) as RunningTotal
from cte1

Retain function in SQL

Have scenario where need to retain values based on condition.
Assign "Change date" on "AA start Date" then check for "Change in Duration".
If "change in Duration" < 60 then 1st Change date will be assigned till next Change in duration > 60
then retain new change date in "AA start date". Sample is given below.
"AA_START_DATE" is final column which I am looking for.
I think this is a type of gap and islands problem, where you want to remember the first date in sequence that is 60+ days from the previous date.
You can handle this by using lag() to get the previous date. Then use a cumulative conditional maximum to get the time when the most recent change occurred:
select t.*,
max(case when change_date > date_add(change_date, interval -60 day) then null else change_date
end) over (partition by cn, aa_code
order by change_date
) as aa_start_date
from (select t.*,
lag(change_date) over (partition by cn, aa_code order by change_date) as prev_change_date
from t
) t
I have achieved this as follows: Any alternate way is appreciable
(select CIN,AA_CODE,EXT_AA_MESSAGE,CHG_DATE,EXP_DATE,PREV_CHG_DATE,CHG_DATE_DUR,AA_START_DTE,
sum(case when AA_START_DTE is null then 0 else 1 end) over (partition by CIN,AA_CODE order by CHG_DATE) as value_partition from (select CIN,AA_CODE,EXT_AA_MESSAGE,CHG_DATE,EXP_DATE,
case when CIN_AA_CODE_FIRST = 1 then NULL else PREV_CHG_DATE end as PREV_CHG_DATE,
case when CIN_AA_CODE_FIRST <> 1 then date_diff(CHG_DATE,PREV_CHG_DATE,DAY) end as CHG_DATE_DUR,
case when CIN_AA_CODE_FIRST = 1 or (case when CIN_AA_CODE_FIRST <> 1 then date_diff(CHG_DATE,PREV_CHG_DATE,DAY) end ) > 60 then CHG_DATE
end as AA_START_DTE,
from
( select CIN,AA_CODE,EXT_AA_MESSAGE,CHG_DATE,EXP_DATE, LAG(CHG_DATE) OVER (PARTITION BY CIN,AA_CODE ORDER BY CHG_DATE ASC) as PREV_CHG_DATE,
rank() OVER (PARTITION BY CIN,AA_CODE ORDER BY CHG_DATE ASC) AS CIN_AA_CODE_FIRST from TABLE )))`

Sql query build

Could you pls help me on the below query,
I have queried a result set by joining two three tables as below,
enter image description here
My requirement is to get the subsequent two dates after 20170701 and before 20170701.
eg. 456 account having date entries like 20160625, 20160725, 20160825, 20160925 , 20170725, 20170825, 20170925..
but the result should be 2 entries < 20170701 > 2 entries
Screenshot attached for example, where green rows should come in the final result.
please help
You can use the sum analytical function as follows:
Select * from
(Select t.*,
Sum(case when date > 20200701 then 1 end)
over (partition by account order by date) as sm_i,
Sum(case when date < 20200701 then 1 end)
over (partition by account order by date desc) as sm_d
From your_table t) t
Where sm_i between 1 and 2 or sm_d between 1 and 2

Counting ED (emergency department) visits but only one per 8 day period

I am working in MS SQL Server 2017 on counting member ED visits where a member may go months between ER visits or may have multiple consecutive days each with a visit. The rule that I am trying to calculate is this:
If a member has more than one ED visit in an 8-day period, include
only the first eligible ED visit. For example, if a member has an
eligible ED visit on January 1, include the January 1 visit and do not
include ED visits that occur on or between January 2 and January 8.
Then, if applicable, include the next eligible ED visit that occurs on
or after January 9. Identify visits chronologically, including only
one visit per 8-day period.
If the days since the last visit is NULL or >= 8 then that is always counted and I have that. The issue I am having is how to look at the running total of Days_Since_Last_Visit to find the next valid visit when there are multiple in a given 8 day period.
In the example below the rows marked in green are flagged for inclusion because the Days_Since_Last_Visit is NULL or >= 8.
The rows highlighted yellow are the ones that should be counted as the first valid visit in the next 8 day period. The bold outline shows the days that are adding up to reach the threshold of 8.
Example data with highlighted entries that should be counted
I have prepared the SQL for the example in the image hoping someone can help me get unstuck.
IF OBJECT_ID('tempdb..#Example') IS NOT NULL
DROP TABLE #Example
CREATE TABLE
#Example (
Subscriber_ID VARCHAR(16),
Member_Seq VARCHAR(2),
Measurement_Year INT,
Visit_Date DATETIME,
)
INSERT INTO #Example (Subscriber_ID,Member_Seq,Measurement_Year,Visit_Date) VALUES
('788768646','02','2019','2019-07-09'),
('788768646','02','2019','2019-08-05'),
('788768646','02','2019','2019-08-18'),
('788768646','02','2019','2019-09-13'),
('788768646','02','2019','2019-09-15'),
('788768646','02','2019','2019-09-19'),
('788768646','02','2019','2019-09-25'),
('788768646','02','2019','2019-10-14'),
('788768646','02','2019','2019-10-21'),
('788768646','02','2019','2019-10-24'),
('788768646','02','2019','2019-10-27'),
('788768646','02','2019','2019-10-28'),
('788768646','02','2019','2019-11-03'),
('788768646','02','2019','2019-11-06'),
('788768646','02','2019','2019-11-18'),
('788768646','02','2019','2019-12-11')
SELECT y.Subscriber_ID,
y.Member_Seq,
y.Measurement_Year,
y.Visit_Date,
y.Prior_Visit_Date,
y.Days_Since_Last_Visit,
CASE
WHEN Days_Since_Last_Visit >= 8 OR Days_Since_Last_Visit IS NULL THEN
'Y'
ELSE
NULL
END Include_Visist,
CASE
WHEN Days_Since_Last_Visit >= 8 OR Days_Since_Last_Visit IS NULL THEN
NULL
ELSE
SUM (CASE
WHEN Days_Since_Last_Visit >= 8 OR Days_Since_Last_Visit IS NULL THEN
NULL
ELSE
y.Days_Since_Last_Visit
END
) OVER (PARTITION BY y.Subscriber_ID, y.Member_Seq,y.Measurement_Year ORDER BY y.Visit_Date)
END Running_Total
FROM (
SELECT x.Subscriber_ID,
x.Member_Seq,
x.Measurement_Year,
x.Visit_Date,
LAG(Visit_Date) OVER (
PARTITION BY x.Subscriber_ID, x.Member_Seq, x.Measurement_Year
ORDER BY x.Visit_Date) Prior_Visit_Date,
DATEDIFF(DAY,
LAG(Visit_Date) OVER (
PARTITION BY x.Subscriber_ID, x.Member_Seq, x.Measurement_Year
ORDER BY x.Visit_Date),
x.Visit_Date) Days_Since_Last_Visit
FROM #Example x
) y
This was challenging. I added some additional test records to make sure it handled a long string of visits close together over several periods.
WITH Example as (
SELECT Subscriber_ID, Member_Seq, Measurement_Year, CAST(Visit_Date as datetime) as [Visit_Date]
FROM (
VALUES
('788768646','02','2019','2019-06-01'),
('788768646','02','2019','2019-06-09'),
('788768646','02','2019','2019-07-09'),
('788768646','02','2019','2019-08-05'),
('788768646','02','2019','2019-08-18'),
('788768646','02','2019','2019-09-13'),
('788768646','02','2019','2019-09-15'),
('788768646','02','2019','2019-09-19'),
('788768646','02','2019','2019-09-25'),
('788768646','02','2019','2019-10-14'),
('788768646','02','2019','2019-10-21'),
('788768646','02','2019','2019-10-24'),
('788768646','02','2019','2019-10-27'),
('788768646','02','2019','2019-10-28'),
('788768646','02','2019','2019-11-03'),
('788768646','02','2019','2019-11-06'),
('788768646','02','2019','2019-11-18'),
('788768646','02','2019','2019-12-11'),
('788768646','02','2020','2020-01-01'),
('788768646','02','2020','2020-01-08'),
('788768646','02','2020','2020-01-09'),
('788768646','02','2020','2020-01-16'),
('788768646','02','2020','2020-01-17'),
('788768646','02','2020','2020-01-24'),
('788768646','02','2020','2020-01-25'),
('788768699','02','2019','2019-06-06'),
('788768699','02','2019','2019-06-07'),
('788768699','02','2019','2019-07-17'),
('788768699','02','2019','2019-08-23')
) t (Subscriber_ID, Member_Seq, Measurement_Year, Visit_Date)
), AllVisits as (
SELECT *,
ROW_NUMBER() OVER(PARTITION BY Subscriber_ID ORDER BY Visit_Date) as [VisitSeq]
FROM Example
), Report as (
SELECT *, Visit_Date as [PeriodStart]
FROM AllVisits
WHERE VisitSeq = 1
UNION ALL
SELECT a.*,
-- if not in the prior period, start a new 8 day period
CASE WHEN a.Visit_Date > r.PeriodStart + 7 THEN a.Visit_Date ELSE r.PeriodStart END
FROM AllVisits a
INNER JOIN Report r
ON r.Subscriber_ID = a.Subscriber_ID AND r.[VisitSeq] + 1 = a.[VisitSeq]
)
select *,
PeriodStart + 7 AS [PeriodEnD],
CASE WHEN Visit_Date = PeriodStart THEN 1 ELSE 0 END as [IsFirstDayOfPeriod]
from Report
where Visit_Date = PeriodStart
order by Subscriber_ID, Visit_Date
The query below gets most of desired records, but not all of them. (This is where it misses a long string of close visits.) I wanted to start here, but but I could not use a subquery or a group by in a recursive part of the CTE. I would have to do something like the above, but the anchor would need both the sequence start and finish. Then recursion for each anchor record would be within it's range. I might try it someday.
SELECT *
FROM Example e
WHERE NOT EXISTS( -- those with no prior within 8 days
SELECT *
FROM Example x
WHERE x.Subscriber_ID = e.Subscriber_ID
AND x.Visit_Date < e.Visit_Date -- prior
AND x.Visit_Date > e.Visit_Date - 8 -- within 8 days
)