Function for business hours in seconds based on calendar table - sql

I'm fairly new to this forum and to T-SQL.
I'm looking for a function to calculate business hours in seconds based on my calendar table. In my calendar table I have 2 columns in it. 1st column is date and opening time and 2nd column date and end time.
I tried the solution from #Ezlo SQL Server counting hours between dates excluding Fri 6pm - Mon 6am
In his solution when its the same date it doubles the time for example the output has to be 75 secs its then 150 secs. I want to be able to call the function in a query like WorkTime (#StartDate DATETIME, #FinishDate DATETIME) while it passes through my calendar table. The startdate and finishdate has to be anything I put as value in it ie a columns (datecreated,dateclosed) with dates.
Ie: a query with 1000 rows like this format.
Scenario 1
TicketID: 111111
DateCreated: 2019-01-01 10:00:52
DateClosed: 2019-01-02 08:35:00
Function result has to be 300 secs while it checked my calendar table.
Scenario 2
TicketID: 111112
DateCreated: 2019-01-02 16:30:00
DateClosed: 2019-01-02 16:15:00
Function result has to be 900 secs while it checked my calendar table.
Scenario 3
TicketID: 111113
DateCreated: 2019-01-02 20:00:00
DateClosed: 2019-01-03 09:30:00
Function result: 3600 secs
Scenario 4
TicketID: 111114
DateCreated: 2019-01-05 20:00:00
DateClosed: 2019-01-07 09:00:00
Function result: 1800 secs
Calendar table
As you can see I have ie 1st of January set to 08:30 so it doesn't calculate the time (Holiday). And so I have a set of Holidays set the same way.
Weekends are left out see calendar table, in that way it is excluded and the time starts to count on the first business day.
I have tried multiple times but with no success of getting it to work as I wish.
Hopefully you gurus can me help me to achieve this.

After days of searching this forum. The answer I was looking for can be found here.
Calculate time difference (only working hours) in minutes between two dates

Related

Timeseries : date time averaging and abnormally detection

I"m dealing with a dataset with 4 week sales data (data will be refreshed every hour) and need to observer for abnormality
I think I'll go with a basic approach, to compare with average numbers and I'm trying to figure out how to best break this down so I can answer some questions below
On average, how many orders received at 9:00 , 15:00 or 16:00 past 30 days
On average, how many orders received at 9:00 every Wednesday (past 4 Wednesdays), at 15:00 every Thursday (past 4 Thursdays),
Not sure how do we go about this (after breaking date/time down to Hour and Weekday columns)
date
order ID
order hour
order weekday
10/07/2022 10:26:12 PM
1111
22
6
10/07/2022 10:27:12 PM
2222
22
6
....
....
....
....
19/07/2022 11:34:19 AM
9998
11
1
19/07/2022 11:34:35 AM
9999
11
1
I would love to get your advice please
Thanks
I've ended up going with a tedious approach.
#get current hour & weekday
now=datetime.datetime.now()
today=datetime.date.today()
current_hour=now.hour
current_weekday=today.weekday()
#create a DF with orders from the same hour & weekday window
same_hour_weekday_df=order_df[(order_df.order_hour==current_hour ) & (order_df.order_weekday==current_weekday) ]
#calculate avg orders generated from the past weeks within the same hour and weekyday timeframe
orders_same_hour_weekday=same_hour_weekday_df['order_created_at'].count()
same_hour_weekday_periods=same_hour_weekday_df['order_week'].nunique()
avg_orders_same_hour_weekday=orders_same_hour_weekday/same_hour_weekday_periods

How to bring future days to past date and then revert to same old days using postgresql?

I have a db with 6 tables. Each table has a list of date and datetime columns as shown below
Table 1 Table 2 .... Table 6
Date_of_birth Exam_date exam_datetime Result_date Result_datetime
2190-01-13 2192-01-13 2192-01-13 09:00:00 2194-04-13 2194-04-13 07:12:00
2184-05-21 2186-05-21 2186-05-21 07:00:00 2188-02-03 2188-02-03 09:32:00
2181-06-17 2183-06-17 2183-06-17 05:00:00 2185-07-23 2185-07-23 12:40:00
What I would like to do is shift all these future days back to the past date (definitely has to be less than the current date) but retain the same chronological order. Meaning, we can see that the person was born first, then he took the exam, and finally, he got his results.
In addition, I should be able to revert the changes and get back the future dates again.
I expect my output to be something like below
Stage 1 - shift back to old days (it can be any day but it has to be in the past and retain chronological order)
Table 1 Table 2 .... Table 6
Date_of_birth Exam_date exam_datetime Result_date Result_datetime
1990-01-13 1992-01-13 1992-01-13 09:00:00 1994-04-13 1994-04-13 07:12:00
1984-05-21 1986-05-21 1986-05-21 07:00:00 1988-02-03 1988-02-03 09:32:00
1981-06-17 1983-06-17 1983-06-17 05:00:00 1985-07-23 1985-07-23 12:40:00
Stage 2 - Shift forward to future days as how it was earlier
Table 1 Table 2 .... Table 6
Date_of_birth Exam_date exam_datetime Result_date Result_datetime
2190-01-13 2192-01-13 2192-01-13 09:00:00 2194-04-13 2194-04-13 07:12:00
2184-05-21 2186-05-21 2186-05-21 07:00:00 2188-02-03 2188-02-03 09:32:00
2181-06-17 2183-06-17 2183-06-17 05:00:00 2185-07-23 2185-07-23 12:40:00
Subtract two centuries:
update table1
set date_of_birth = date_of_birth - interval '200 year';
You can do something similar for all the other dates.

How to get time difference in months in SQL

Here is how my current dataset is formatted:
USER START_DATE END_DATE NB_MONTHS
--------------------------------------------
111 2020-01-01 2021-02-01 13
222 2020-05-17 2020-09-28 16
333 2020-02-01 2020-03-01 0
Each of my users currently have a start date and an end date for an action they've completed.
I wish to find the time duration of their action in MONTHS (as defined by the NB_MONTHS_ flag).
Here is my current query to get this NB_MONTHS flag:
SELECT
USERS,
FLOOR((END_DATE)-(START_DATE))/30.00 as NB_MONTHS
FROM
TABLE1;
I am currently rounding down this flag as that is what makes most sense for my analysis.
Here is where I get an issue:
My user 333 who has technically taking 1 month to complete the action (duration of February) is currently beeing flagged as "0 months" because February has 28 days (which doesnt work with my query).
Anyone know how I can avoid this problem?
Does datediff() do what you want?
SELECT USERS,
DATEDIFF(MONTH, START_DATE, END_DATE) as NB_MONTHS
FROM TABLE1;

How to implement grouping and filters inside a nested for loop in pig

I am new to pig and stuck with implementation of an algorithm. I have a data set which contains start date , drop date , market and size of an object.
Here is what i need to implement
Find unique start dates (implemented)
For each unique date filter out the values which have a start date <= unique date <= drop date.
Group the filtered values by market.
Find the total size of objects in the market.
Final output will be TotalSize for each market each day. The trick is an object can be alive across days and thus it's size need to be included in sum calculation for each day it is alive. An object dies on the drop date.
I have not been able to figure out a way to implement Step 2,3 and 4 of the algorithm efficiently in pig.
Another question is, if it is at all possible to implement this requirement in pig.
Here is what I have tried::
req_data = FOREACH uniqueStartDays {
temp = FILTER joined_data BY joined_data.startDay <= uniqueStartDays.startDay AND uniqueStartDays.startDay <= joined_data.dropDay;
group_temp = GROUP temp BY market;
FOREACH (group) GENERATE market, startDay, assetSizeInMb;
};
Any help will be appreciated.
Adding the sample data and the expected result
Market Start_Time End_Time Drop_Time Size
Allahabad 2016-08-09 12:00 2016-08-09 1:00 2016-08-13 4:00 120
Allahabad 2016-08-10 2:00 2016-08-10 3:00 2016-08-12 5:00 60
Allahabad 2016-08-09 3:00 2016-08-09 4:30 2016-08-09 5:30 80
Result:
Market Day TotalSize
Allahabad 2016-08-09 200 (120+80)
2016-08-10 180 (120+60)
2016-08-11 180 (120+60)
2016-08-12 180 (120+60)
2016-08-13 120

Rails - how to fetch from database the closest records according to date?

I have in database stored records like this:
ID| date_column
1 | 2013-02-10 10:00:00
2 | 2013-02-10 11:00:00
3 | 2013-02-10 12:00:00
4 | 2013-02-10 13:00:00
5 | 2013-02-11 14:00:00
6 | 2013-02-11 22:00:00
I am trying to fetch 3 records, which are the closest ones to the today's date. For example, let's suppose today is 2013-02-10, so I would need to fetch 3 records with today's date (2013-02-10 11:00:00, 2013-02-10 12:00:00, 2013-02-10 13:00:00), but for example if today is 2013-02-15, I would need to get the closest 3 records, which are in this case 2013-02-10 13:00:00, 2013-02-11 14:00:00 and 2013-02-11 22:00:00?
Could you help me, please, how to do that?
Thank you
Assuming you're using ActiveRecord right?
This query will grab the three closest dates to "now" in the past:
time_to_check = Time.now
TableObjectName.where("date_column <= ?", time_to_check ).limit(3).order("date_column desc")
This query will grab the three closest dates to "now" in the future:
TableObjectName.where("date_column >= ?", time_to_check ).limit(3).order("date_column desc")
The only thing I can think of and this seems inefficient, but I can't think of a SQL way of doing this, is you now have two arrays basically with six records.
Three in the future (if there are any)
Three in the past (if there are any).
I'd then loop through each and compare how much time has elapsed between each record from the timeToCheck variable.
Whichever three have the smallest amount of time difference, Add those to your final array.
This will get the 3 closes to a specific time, which I'm using noon on your target day. This will ensure today's results come ahead of any other day.
TableObjectName.all(order: "abs(timediff('2013-02-10 12:00:00', date_column))", limit: 3).