Finding the exact overlapping time - sql

with tickets as (
select o.SSTID, o.open_Id, o.Createddatetime openTime, c.Createddatetime closeTime
from dbo.Close_ticket c
inner join dbo.Openticket o ON o.SSTID = c.SSTID and c.Open_ID=o.open_id
)
select t1.SSTID,
SUM(isnull(datediff(hour
, case when t1.openTime > t2.openTime then t1.openTime else t2.openTime end
, case when t1.closeTime > t2.closeTime then t2.closeTime else t1.closeTime end),0)) as [OverLappingtime]
from tickets t1
left join tickets t2 on t1.SSTID = t2.SSTID
and t1.openTime < t2.closeTime and t2.openTime < t1.closeTime
and t1.open_id < t2.open_id
group by t1.SSTID
This is my code where each ticket is compared to every other ticket to find the total overlapping time. But if I create more tickets the total time exceeds 24 hours when all the tickets where created on the same day. How can I find the exact overlapping time? If we see the first three tickets, the 2nd and the third ticket were opened and closed within the opening and closing time of the first ticket.
I need the exact overlapping time.
This is my Openticket table.
[Open_ID,SSTID,Createddatetime]
- 1,1,2020-04-27 06:40:32.337
- 2,1,2020-04-27 12:40:32.337
- 3,1,2020-04-27 14:40:32.337
- 4,1,2020-04-27 15:40:32.337
- 5,1,2020-04-27 18:40:32.337
This is my Close_ticket table.
[Close_id,open_id,SSTID,Createddatetime]
- 1,1,1,2020-04-27 20:40:32.337
- 2,2,1,2020-04-27 15:40:32.337
- 3,3,1,2020-04-27 16:40:32.337
- 4,4,1,2020-04-27 17:40:32.337
- 5,5,1,2020-04-27 21:40:32.337

You keep saying "the logic I've used so far is the one I mentioned" but at no point have you actually mentioned this logic in any useful form so that anyone can understand what it is you are doing: all you are doing is stating numbers with no indication on how you calculated these numbers.
Please provide a step by step guide to show how you calculated an overlap figure of 4 hours for the first 3 tickets.
For example, taking your data but moving the start/end times to the hour (rather than 40:32.337) for the sale of simplicity, we have this:
Possible overlap calculations:
2 overlaps 1 by 3 hours => overlap is 3
3 overlaps 1 by 3 hours => overlap is 3
You want to calculate overlap of both 2 & 3 compared to 1: 3 + 3 = 6
You only want the overlap when all 3 tickets overlap: 1
You don't want to double count any overlap: 2 overlaps 1 by 3 hours, 3 overlaps 1 by 3 hours, 2 & 3 overlap each other by 1 hour (double count) => 3 + 3 - 1 = 4
So which of these possible calculations are you using or are you using completely different logic and, if so, what it that logic?

Related

SQL query to find the average time differences between two statuses

I am trying to find the time between status changes for tickets. The statuses are A,B,C,D,E. I need to identify where the bottlenecks are in the system. The table looks something like this:
ticket_no
created_at
current_status
next_status
1
12/2/2022
A
B
1
12/3/2022
B
C
1
12/3/2022
C
B
1
12/4/2022
B
C
1
12/4/2022
C
E
2
12/4/2022
A
C
2
12/5/2022
C
D
2
12/7/2022
D
E
As you can see for ticket 1, it cycled between statuses B and C before finally ending at E. I want to calculate the average time tickets take to move between specific statuses (say A->C, C->E). It’s a bit confusing because tickets can return to previous statuses and tickets don’t need to move through every status. There is an order to the statuses but you can return to a previous state.
Any ideas?
I’ve tried a bunch of things, like lagging (only looks at previous/next), or even pivoting with case statements and subtracting but it doesn't seem to work.
Again the ask is to find the time spent (on average) to go between 2 specific statuses, such as A->C or C->E
Here's my query so far. The idea is to pivot things and just subtract, but I'm really not sure this is gonna be valid
with pv_times as (
select ticket_no,
max(case when current_status='A' and next_status='B' then created_at else null end) as ab_time,
max(case when current_status='A' and next_status='C' then created_at else null end) as ac_time
FROM statuses
GROUP BY 1
)
select * from pv_times
# subtract times to find diff...but is this even valid?
time spent to go between 2 specific statuses
Enumerate all such statuses.
This is the lower diagonal triangle of a 5 × 5 matrix.
Then do a JOIN (.merge) to aggregate all observed
transitions against that vector of possibilities,
.count()'ing the number of them we observed.

Issues with Criteria in SQL

I am really hoping someone can help me, i have a table as such:
Period Client Active
jan-20 x 1
feb-20 y 0
mar-21 z 1
jan-21 t 0
mar-21 f 1
jan-21 f 0
dec-20 f 0
The period is as format 'YYY-MM-DD'.
I have a table (x) that has multiple periods, clients and an active status of 1 or 0.
I want to pull in only clients where the current month active status is '1' but the active status for all previous months of the current month are '0'.
what i am getting at the moment, is results that show the client, but where i dive deeper into that client, it has months where active status = '1' in previous months, but them periods are excluded from my results, when in actual fact that specific client shouldn't be in my results at all.
FYI - my current period will always be the MAX period within my table (x).
This is the code i am currently using - but is not working as pulling in clients that shouldnt be in there.
*SELECT
e.EmeaChannel,
fc.PeriodKey,
fc2.PeriodKey,
fc.Merchantkey AS Clients,
fc.RevenueActive,
fc2.RevenueActive
FROM [Fact].[ClientCountFull] fc
inner join [Fact].[ClientCountFull] FC2 on
FC2.PeriodKey >= DATEADD(MONTH, -16, FC.PeriodKey)
AND FC2.PeriodKey < FC.PeriodKey
AND FC.MerchantKey = FC2.MerchantKey
AND fc.EmeaChannelKey = fc2.EmeaChannelKey
inner join Dimension.EmeaChannel e on e.emeachannelkey = fc.emeachannelkey
inner join dimension.account a on a.MerchantKey = fc.MerchantKey
where
AccountStatus = 'Open'
and e.EmeaChannel = 'CMS'
and fc.RevenueNew = 1
and fc.RevenueActive = 1
and fc2.RevenueActive = 0
order by fc.PeriodKey desc*
If I understand correctly, you can use aggregation. Let me start by assuming that period has a reasonable format of YYYY-MM rather than using the (rather useless) month name. Then you can use:
select client
from t
where active = 1
group by client
having min(period) = '2021-03';
In your case, you will need to convert the period to a date -- or at least to YYYY-MM format. That depends on the database you are using, and date/time functions are notoriously database-dependent.

Repetition of weekend's pattern after every 7 days in SQL

I have a requirement to repeat the Week-Off pattern in table2 based on given week-off frequency in table1 .
Frequency: means it could be a number with multiple of 7 only like (7 , 14 , 21 ,28 so on..)
Week-Off: for each employee week-off could be Nth rows.
Please find the SQL fiddle for demo
http://sqlfiddle.com/#!18/7cb68a/2
In given screenshot, If you have noticed "WhatIsGetting" field then it's working only for two week-off after that it's getting null bcz RuleTableTemp.ShiftId is not matching with TempMainTable.ShiftId.
I need a experts help on my requirement to repeat the week-off for given date range based on given RuleTableTemp.WeekOffFrequencyInDays.
For now in demo I have used '7' as a hard-coded value for week-off frequency like this
((te.Id / 7) + 1 )
Please find the screen shot for more clarifications.
Feel free to ask if any information is misleading or not cleared.
Note: For now I have taken only example of one employee in real scenario it could be nth employees and week-off should repeat for each employee for given date range based on given week-off frequency...
Conditions or points to remember:
RuleTableTemp: for now we have two ShiftPattern for each employee but it may vary, it could be 3 or 4 patterns too.
RuleTableTemp Filed's name WeekOffFrequencyInDays having value '7' for EmployeeId(4536) but it can also vary for each employee and yes for eg. if there are 4 entries for "4536" employee then WeekOffFrequencyInDays value will be same for all.
Example 1:
if (RuleTableTemp.WeekOffFrequencyInDays == 7 ) {
// ShiftPattern's count is 2:
// ShiftPattern will switch after every 7 days.
}
Example 2:
if ( RuleTableTemp.WeekOffFrequencyInDays == 14) {
// if ShiftPattern's count is 3:
// ShiftPattern will keep switching between 3 patterns after every 14 days
}
Example 3:
if ( RuleTableTemp.WeekOffFrequencyInDays == 21) {
// if ShiftPattern's count is 1 means no switching is required
}
I took almost 1 hour to explain my requirements but somebody still down-vote it instead of asking what was uncleared... so said to see this.... :(
This answers the original version of the question.
This logic should match the shifts:
SELECT mt.* ,
(SELECT rtt.ShiftPattern
FROM RuleTableTemp rtt
WHERE rtt.EmployeeID = mt.EmployeeId AND
rtt.id = (((mt.seqnum - 1) % 14) / 7) + 1
) as Sh
FROM (SELECT mt.*,
ROW_NUMBER() OVER (PARTITION BY mt.EmployeeId ORDER BY id) as seqnum
FROM TempMainTable mt
) mt;
Note that I added an explicit sequence number on the main table. This is just to be sure that the numbers are doing what you really want (automatically generated ids can be a problem).
The key to the logic is modulo arithmetic -- taking the remainder when the sequence number of divided by 14 and then using that for matching to the week.
Here is a db<>fiddle.

Join check view with a calendar view

I have two views. One with checks:
Check_Id Issued_Date Cleared_Date Amount
1 2017.01.03 2017.02.04 100
2 2017.03.03 2017.04.04 100
3 2017.08.03 100
...
And another is just a calendar:
Day
2001.01.01
2001.01.02
2001.01.03
...
2100.12.31
I need a scaffold view for Tableau. What i'd like to achieve is, for every check, have a record in the dates between Issued date to the cleared date. If there is no cleared date, just go to the end of times (2100.12.31 in this case).
Ie, for the Check_id 1:
Day Check_ID
2017.01.03 1
2017.01.03 1
2017.01.03 1
2017.01.03 1
...
2017.02.04 1
2017.08.03 3
2017.08.04 3
2017.08.05 3
2017.08.06 3
...
2100.12.31 3
Any tip or stuff i'd read to get it? Thanks!
This is a non-equijoin:
select ca.day, c.check_id
from checks c join
calendar ca
on ca.day >= c.issued_date and
(c.cleared_date is null or c.cleared_date >= ca.date);

Group by time span in rails

I want get output from users table based on time of creation of record. Time is stored in created_at column.
Output will be like this:
Time user count
2 am - 6 am 10
6 am - 10 am 5
10 am - 2 pm 5
2 pm - 6 pm 5
6 pm - 10 pm 5
10 pm - 2 am 5
I can't do group by created_at. Solution I found is to create another column say time_span and update that column to 2 am - 6 am if created_at time falls in this span and then I can do group_by on time_span column. Any better solution?
My suggestions is to create another column on the database, this way you avoid calculations on selects at an expense of a simple column.
I'm not sure what you mean by not being able to use group_by, but the following will work:
hours = Users.all.collect {|u| u.created_at.hour}
ranges = [(2...6), (6...10), (10...14), (14...18), (18...22), (22...26)]
summary = hours.group_by {|h| ranges.find {|r| r === (h<2 ? h+24 : h)}}
ranges.each {|r| puts "#{r} = #{(summary[r] || []).length}"}
There are probably opportunities to simplify this and you could push the grouping up into the database if you'd like, but I thought I'd go ahead and share.