How to calculate periodIds using SQL server - sql-server

I have a table1 which stores the data for multiple dates say (between 2022-01-01 to 2022-01-10) and I have another table2 which has time interval and has every 5mins information of dates available in table1 (i.e. 288 records for each day in above table).
Now, How I can write a query for table 2 to calculate time interval for each specific date in table 1. Say I need time intervals between
2022-01-01 12:00:00 to 2022-01-01 02:00:00
2022-01-02 00:05:00 to 2022-01-02 23:00:00
2022-01-04 00:05:00 to 2022-01-10 15:00:00
I tried using DATEDIFF function but that is not giving the results. let's say If I take date 2022-01-02 00:00:00 then my time interval should go back to 1 it should be 2 for 2022-01-02 00:05:00
Below is the example of data:
Table 1:
ID Start date End date
20030917.D0001 2003-09-17 14:10:00 2003-09-18 14:20:00
Table 2:
Date Time interval Amount
2003-09-17 1 150
2003-09-17 2 100
2003-09-17 3 200
2003-09-17 288 250
2003-09-18 1 250
2003-09-18 2 300
2003-09-18 3 1100
2003-09-18 288 150
The time interval in table 2 is every 5 mins of that particular date. Now I need to fetch the data from table 2 which matches with specific date and time in table1

i'm guessing here, if you are looking to return data from table2 with specific time and the table formatted like below
table1
tbl1id
Date
1
2022-01-01
2
2022-01-10
table2
tbl2id
tbl1id
Time
1
1
12:00:00
2
1
12:05:00
3
1
12:10:00
your query should be
select *
from table2
where Time between '12:00:00' and '02:00:00'
and tbl1id
in
(
select tbl1id
from table1
where Date = '2022-01-01'
)
however it you are looking for just looking for calculate time interval in Minute
DECLARE #startdate DATETIME2 = '2022-01-02 00:00:00';
DECLARE #enddate DATETIME2 = '2022-01-02 00:05:00';
SELECT DATEDIFF(Minute, #startdate, #enddate);
that should do it.

Related

How to differentiate if difference between dates in weekly on monthly?

I have a table in which employee's loan details are being saved. Some employee get loan on weekly basis and wish to return each installment weekly and some wish to return installments monthly.
I want to get the total duration on the loan period if employee wishes to return installments weekly then it should give output like 5 Weeks or 10 Weeks but if employee wishes to return installments monthly it should give result like 4 Months or 15 Months.
Here is the sample data
LoanID DueDate AmountToBePaid
2 2019-01-01 500
2 2019-01-07 500
2 2019-01-14 500
2 2019-01-21 500
2 2019-01-28 500
3 2019-01-01 1500
3 2019-02-01 1500
3 2019-03-01 1500
3 2019-04-01 1500
Here is what I've tried but it gives output in weeks no matter if the installments are to be paid monthly as for loan id 3.
SELECT
LoanId,
DATEDIFF(WEEK, inst_start, inst_end) weeks
FROM LoanMaster LM
INNER JOIN (
SELECT
dateadd(month, -1,min(duedate)) inst_start,
max(duedate) inst_end
FROM LoanDetail
) LD
ON LM.ID = LD.LoanID
Out should be like:
LoanId Duration
2 4 Weeks
3 3 Months
If your data strictly follow the rule that for the same LoanID the DueDates will be either only consecuctive weeks or only consecuctive months, then we can deduce the period by dividing the range with the row count:
SELECT
LoanID,
case
when datediff(month,min(DueDate),max(dueDate))=count(*)-1
then str(datediff(month,min(DueDate),max(dueDate)))+' Months'
else
str(datediff(week,min(DueDate),max(dueDate)))+' Weeks'
end as Duration
FROM LoanMaster LM
GROUP BY LOANID

Get hour from datetime range SQL server 2008

I have table containing branch id and branch starttime and endtime
BRANCHID SHIFTID STARTTIME STOPTIME
1 1 1900-01-01 00:01:00.000 1900-01-01 23:58:00.000
4 4 1900-01-01 07:30:00.000 1900-01-01 18:00:00.000
5 5 1900-01-01 06:30:00.000 1900-01-01 19:00:00.000
6 6 1900-01-01 06:30:00.000 1900-01-01 17:00:00.000
7 7 1900-01-01 00:30:00.000 1900-01-01 18:00:00.000
Now i want to get the number of hours in date range like :
BRANCHID Hours
1 1
1 2
1 3
. .
. .
The resultant table containing branch id and hours in time interval. like branch 1 start time is 00:01:00 - 23:58:00. Than branch id 1 time interval contains following hours 1,2,3,4,5,6 and so on..
select
branchid from table t1
cross apply
(
select n from numbers
where n >=datepart(hour,starttime) and n<=datepart(hour,stoptime)
) b
Below are some links on the numbers table used..
1.http://dataeducation.com/you-require-a-numbers-table/
2.https://dba.stackexchange.com/questions/11506/why-are-numbers-tables-invaluable
Create temp table #hours.
create table #Hours
(
BId int,
[Hour] int
)
Get max and min datetime.
While (#minDateTime < #maxDateTime)
begin
insert into #Hours values (#brID,Datepart(hour,#minDateTime))
set #minDateTime = DATEADD(hh,1,#minDateTime)
end
Select * from #Hours

T-SQL how to calculate datediff from previous or next row on log?

I use MS SSMS 2008 R2 to extract data from our company management software, which registers our employee actions and schedules. The table has and ID field, which is unique to each entry. job is the activity the user is performing. user is the user ID. start_time and duration are exactly that. Then there is a "type" where 0 is login (the user logs into the job) and 1 is available time (while performing a job the user may be available or not). "reason" is the reason why the user has become unavailable (break, coffee, lunch, training, etc). Type 0 entries have no reason so reason is always null.
I need to extract the unavailable times by reason and all I'm being able to achieve is to do a DATEADD of duration to start_time in order to get end_time and then use Excel to manually calculate the times for each row.
The SQL table looks like this:
id job user start_time duration type reason
4436812 3 758 05-06-2015 09:00 125670 0 NULL
4436814 3 758 05-06-2015 09:00 6970 1 1004
4436944 3 758 05-06-2015 09:14 39280 1 1004
4437119 3 758 05-06-2015 10:20 0 1 1002
4437172 3 758 05-06-2015 10:35 18470 1 1004
4437312 3 758 05-06-2015 11:09 3960 1 1004
4437350 3 758 05-06-2015 11:16 0 1 1006
4437360 3 758 05-06-2015 11:19 30080 1 1004
4437638 3 758 05-06-2015 12:13 6730 1 1004
4437695 3 758 05-06-2015 12:24 0 1 1007
4438227 3 758 05-06-2015 13:43 NULL 0 NULL
4438228 3 758 05-06-2015 13:43 NULL 1 NULL
(job = 3 and user = 758)
This is the query I made:
select CONVERT(date,start_time) Data, a.job, a.user, convert(varchar(15),convert(datetime,a.start_time),108) StartTime, a.duration duracao,
convert(varchar(15),convert(datetime,DATEADD(second,a.duration/10,a.start_time)),108) EndTime, a.type, a.reason
from schedule_log a
where a.job = 3
and a.user = 758
and CONVERT(date,start_time) = '20150605'
order by a.start_time, a.type
Which translates to:
Date job user LogTime Avail NotAvail
2015-06-05 3 758 04:44:01 04:10:23 00:33:38
So, for each reason, I have to do a DATEDIFF from end time (start+duration) to either the next type 1 start_time or the previous type 0 end time, which ever happened first (the user may become unavailable and then logoff).
How do I do this?
ps: duration is in tenths of second.
Ok, here is my updated suggestion. It is broken into three steps for clarity, but the temp tables are unnecessary - they could become subqueries.
Step 1: Calculate the end time for each period of activity, excluding logins.
Step 2: Join each row to the row that occurred immediately after it, to get the unavailable time following each reason. Note: some of your timestamps do not line up properly, possibly as a result of storing duration in seconds but timestamps only to the minute.
Step 3: Total the unavailable time, and subtract from the duration of the login to get the available time.
Step 4: Total the unavailable time by reason.
SELECT *
,dateadd(s, duration / 10, start_time) AS Endtime
,row_number() OVER (
PARTITION BY job ,[user] ORDER BY start_time, [type]
) AS RN
INTO #temp2
FROM MyTable
WHERE [type] = 1
SELECT a.[user]
,a.job
,a.reason
,a.start_time
,a.type
,a.duration / 10 AS AvailableSeconds
,datediff(s, a.Endtime, b.start_time) AS UnavailableSeconds
INTO #temp3
FROM #temp2 a
LEFT JOIN #temp2 b
ON a.[user] = b.[user]
AND a.job = b.job
AND a.RN = b.RN - 1
SELECT cast(a.start_time AS DATE) AS [Date]
,a.job
,a.[user]
,b.duration / 10 AS LogTime
,b.duration / 10 - sum(UnavailableSeconds) AS Avail
,sum(UnavailableSeconds) AS NotAvail
FROM #temp3 a
LEFT JOIN MyTable b
ON a.job = b.job
AND a.[user] = b.[user]
AND b.[type] = 0
AND b.duration IS NOT NULL
GROUP BY cast(a.start_time AS DATE)
,a.job
,a.[user]
,b.duration
SELECT cast(a.start_time AS DATE) AS [Date]
,a.job
,a.[user]
,a.reason
,sum(UnavailableSeconds) AS NotAvail
FROM #temp3 a
where reason is not null
GROUP BY cast(a.start_time AS DATE)
,a.job
,a.[user]
,a.reason

DateTime in sql only comparing the time

ID DateTime Code
---------- -------------- ----------
58 2015-01-01 20:00:00 1111
58 2015-01-11 10:00:00 8523
58 2015-01-11 03:00:00 4555
58 2015-01-19 00:01:00 8888
9 2015-01-01 20:00:00 4444
how do i count the number of codes for a specific ID ignoring which date it is but it must be between 20:00:00 and 06:00:00
select count(code) as count from table 1 where ID='58' and DateTime between '20:00:00' and '06:00:00'
the expected output would be
count
3
SELECT count(code) as count
FROM table1
WHERE
ID='58' and
(CAST(DateTime as time) >= '20:00'
or CAST(DateTime as time) <= '06:00')
EDIT: John, I understand the issue. Here is a full solution to handle those cases:
In order to use variables:
DECLARE #HourBegin time = '07:00'
DECLARE #HourEnd time = '17:30'
SELECT count(code) as count
FROM table1
WHERE
ID='58' and
(CAST(DateTime as time) between #HourBegin and #HourEnd or
((CAST(DateTime as time) <= #HourEnd or
CAST(DateTime as time) >= #HourBegin) and
#HourBegin > #HourEnd)
)
Almost the same as previous answer, but with hours it looks nicer for me and might be you need DISTINCT code
SELECT count(DISTINCT code) as count
FROM table1
WHERE
ID='58' and
(DATEPART(HOUR,DateTime) >= 20
or DATEPART(HOUR,DateTime) < 6)
UPDATED: changed from <= 6 to < 6
Update
This answer applies to MySQL.
When I started writing the answer, the question was tagged mysql and sql-server. The OP edited it in the meantime.
This query should do what you want on MySQL.
SELECT count(code) AS `count`
FROM `table 1`
WHERE ID='58'
AND TIME(`DateTime`) NOT BETWEEN '06:00:01' AND '19:59:59'
The MySQL function TIME() extracts only the time component from a DATETIME value.
On version 5.7, MySQL added support for fractional seconds (up to 6 digits) on DATETIME columns. The query above will include the entries having time greater than 06:00:00 but smaller than 06:00:01 (events that happened during the first second after 6 AM sharp).
For MySQL 5.7 and newer, the correct query is:
SELECT count(code) AS `count`
FROM `table 1`
WHERE ID='58'
AND (TIME(`DateTime`) <= '06:00:00' OR '20:00:00' <= TIME(`DateTime`))
I don't know about SQL Server.

How to convert a float column into a datetime

I have a table that contains a DateField(DataType : DateTime) and TimeField(DataType : Float)
My output should be DateTime . My tables are in SQL Server 2008
Here is an example :
Table A
ID StartDate StartTime
1 2012-06-08 00:00:00.000 1223
2 2012-08-07 00:00:00.000 910
3 2012-05-02 00:00:00.000 1614
4 0094-07-13 00:00:00.000 1245
5 1994-04-18 00.00:00.000 2573
I need to get my output in such a way that I should it should validate for the correct time and correct date and append these two and insert into table B
Table B :
ID StartDateTime
1 2012-06-06 12:23:00.000
2 2012-08-07 09:10:00.000
3 2012-05-02 16:14:00.000
Note that I intentionally left rows 4 and 5 out of the result set; these rows should be ignored because they don't contain valid datetime or time data.
Have you considered correcting the design, and storing the date/time together, or at least storing date and time using the proper data types? In the meantime:
SELECT StartDate + STUFF(RIGHT('0' + RTRIM(StartTime), 4), 3, 0, ':')
FROM dbo.table
WHERE ISDATE(StartDate) = 1 AND CONVERT(INT, StartTime) < 2400
-- wow what a bunch of absolute garbage data you have
-- what Government agency are you paying to provide this data?
AND CONVERT(INT, StartTime) % 100 BETWEEN 0 AND 59;

Resources