Get the total sum hours in a column SQL SERVER - sql

Sql Fiddle Example
I have this result table
Id Hours
----- -----
1 09:00
2 09:30
3 10:00
4 10:30
5 11:00
6 11:30
7 12:00
8 12:30
9 13:00
10 13:30
11 14:00
12 14:30
13 15:00
14 15:30
15 16:00
16 16:30
17 17:00
18 17:30
19 18:00
I need to get the total sum hours, for example from 09:00 to 18:00 there is a total of :
9
hours, I need to get this sum of hours

Your table schema hour is varchar, you need to cast as time, then do the calculation
SELECT datediff(hour,min(cast(hour as time)),max(cast(hour as time)))
FROM Timetable
sqlfiddle
NOTE
I would suggest your hour column as datetime or time instead of varchar. because hour column intention is time.
EDIT
If your time is 9:00 to 17:30, you can try to use datediff minute to get the total diff minutes then divide 60 to get hours.
SELECT datediff(minute,min(cast(hour as time)),max(cast(hour as time))) / CAST(60 as float)
FROM Timetable
https://dbfiddle.uk/?rdbms=sqlserver_2017&fiddle=6e005cdfad4eca3ff7c4c92ef14cc9c7

use datediff function
select datediff(hour,min(h),max(h)) from
(
select CAST(hour AS TIME) as h from Timetable
) as t
strongly disagreed to put time value in varchar ,so it is better change your data type from varchar to time

declare #a time = '13:00',#b time = '17:30' --- Here you can give time, what you need.
select distinct convert(varchar(20)
, datediff(MINUTE,#a,#b) / 60)
+ ':' +
convert(varchar(20), datediff(MINUTE,#a,#b) % 60)
from #Timetable
where hour in (#a,#b)
For your SQL Fiddle Sample Data.

Obviously, you need to use datediff(). However, you should be doing the datediff() in minutes or seconds and then converting to hours:
SELECT datediff(minute, min(cast(hour as time)), max(cast(hour as time))) / 60.0
FROM Timetable;
This will handle the case where the number of hours is not an exact number of hours.

Related

SUM of production counts for "overnight work shift" in MS SQL (2019)

I need some help regarding sum of production count for overnight shifts.
The table just contains a timestamp (that is automaticaly generated by SQL server during INSERT), the number of OK produced pieces and the number of NOT OK produced pieces in that given timestamp.
CREATE TABLE [machine1](
[timestamp] [datetime] NOT NULL,
[OK] [int] NOT NULL,
[NOK] [int] NOT NULL
)
ALTER TABLE [machine1] ADD DEFAULT (getdate()) FOR [timestamp]
The table holds values like these (just an example, there are hundreds of lines each day and the time stamps are not fixed like each hour or each 30mins):
timestamp
OK
NOK
2022-08-01 05:30:00.000
15
1
2022-08-01 06:30:00.000
18
3
...
...
...
2022-08-01 21:30:00.000
10
12
2022-08-01 22:30:00.000
0
3
...
...
...
2022-08-01 23:59:00.000
1
2
2022-08-02 00:01:00.000
7
0
...
...
...
2022-08-02 05:30:00.000
12
4
2022-08-02 06:30:00.000
9
3
The production works in shifts like so:
morning shift: 6:00 -> 14:00
afternoon shift: 14:00 -> 22:00
night shift: 22:00 -> 6:00 the next day
I have managed to get sums for the morning and afternoon shifts without issues but I can't figure out how to do the sum for the night shift (I have these SELECTs for each shift stored as a VIEW for easy access).
For the morning shift:
SELECT CAST(timestamp AS date) AS Morning,
SUM(OK) AS SUM_OK,
SUM(NOK) AS SUM_NOK
FROM [machine1]
WHERE DATEPART(hh,timestamp) >= 6 AND DATEPART(hh,timestamp) < 14
GROUP BY CAST(timestamp AS date)
ORDER BY Morning ASC
For the afternoon shift:
SELECT CAST(timestamp AS date) AS Afternoon,
SUM(OK) AS SUM_OK,
SUM(NOK) AS SUM_NOK
FROM [machine1]
WHERE DATEPART(hh,timestamp) >= 14 AND DATEPART(hh,timestamp) < 22
GROUP BY CAST(timestamp AS date)
ORDER BY Afternoon ASC
Since we identify the date of each shift by its start, my idea would be that the result for such SUM of night shift would be
Night
SUM_OK
SUM_NOK
2022-08-01
xxx
xxx
for interval 2022-08-01 22:00:00.000 -> 2022-08-02 05:59:59.999
2022-08-02
xxx
xxx
for interval 2022-08-02 22:00:00.000 -> 2022-08-03 05:59:59.999
2022-08-03
xxx
xxx
for interval 2022-08-03 22:00:00.000 -> 2022-08-04 05:59:59.999
2022-08-04
xxx
xxx
for interval 2022-08-04 22:00:00.000 -> 2022-08-05 05:59:59.999
...
...
...
After few days of trial and error I have probably managed to find the needed solution. Using a subquery I shift all the times in range 00:00:00 -> 05:59:59 to the previous day and then I use that result in same approach as for morning and afternon shift (because now all the production data from night shift are in the same date between 22:00:00 and 23:59:59).
In case anyone needs it in future:
SELECT
CAST(nightShift.shiftedTime AS date) AS Night,
SUM(nightShift.OK) AS SUM_OK,
SUM(nightShift.NOK) AS SUM_NOK
FROM
(SELECT
CASE WHEN (DATEPART(hh, timestamp) < 6 AND DATEPART(hh, timestamp) >= 4) THEN DATEADD(HOUR, -6, timestamp)
WHEN (DATEPART(hh, timestamp) < 4 AND DATEPART(hh, timestamp) >= 2) THEN DATEADD(HOUR, -4, timestamp)
WHEN (DATEPART(hh, timestamp) < 2 AND DATEPART(hh, timestamp) >= 0) THEN DATEADD(HOUR, -2, timestamp)
END AS shiftedTime,
[OK],
[NOK]
FROM [machine1]
WHERE (DATEPART(hh, cas) >= 0 AND DATEPART(hh, cas) < 6)) nightShift
WHERE DATEPART(hh,nightShift.shiftedTime) >= 22
GROUP BY CAST(nightShift.shiftedTime AS date)
ORDER BY Night ASC
PS: If there is anything wrong with this approach, please feel free to correct me as I'm just newbie in SQL. So far this seems to do exactly what I needed.

Get hourly data based on StartDate

For Example,
I had data something like this :-
batch MIN MAX TIME
X 10 20 2018-07-12 10:29:00.000
X 30 50 2018-07-12 10:30:00.000
X 50 30 2018-07-12 10:31:00.000
| | | |
X 40 20 2018-07-12 11:45:00.000
Now I want hourly data based on start time, For example :-
DURATION MIN
2018-07-12 10:29:00.000-2018-07-12 11:29:00.000 10
2018-07-12 11:30:00.000-2018-07-12 12:30:00.000 10
How can I get this?(Get Min Value For every hour based on Start Time)
dateadd function allows you to add or subtract days,hours, minutes to a date.
Consider The below query
select dateadd(HOUR, -1, getdate()) as time_added,
getdate() as curr_date
The -1 is for subtracting one hour (adding negative one hour)
The result of above query is :
timeadded curr_date
2018-07-12 13:25:31.603 2018-07-12 14:25:31.603
Instead of getdate() use your startdate
In your case it would be
select min from table where time<#starttime and time> dateadd(HOUR, -1, #starttime)

Extract hours as 1 - 48 from half hour interval times

I have the below data.
0:00:00
0:30:00
1:00:00
1:30:00
2:00:00
2:30:00
3:00:00
3:30:00
4:00:00
4:30:00
5:00:00
5:30:00
6:00:00
6:30:00
I can extract the hour the using EXTRACT(HOUR FROM TIMESTAMP) but this will give me 24 hours.
But now I need to some different calculation where I can get numbers from 1-48 based on the time given.
Something like this:
0:00:00 1
0:30:00 2
1:00:00 3
1:30:00 4
2:00:00 5
2:30:00 6
3:00:00 7
3:30:00 8
4:00:00 9
4:30:00 10
6:00:00 13
6:30:00 14
Note the skipped 11 and 12, for the absent values 5:00 and 5:30.
Is there any possibilities that I can get that result in PostgreSQL?
Simply use formula 1 + extract(hour from 2 * tm) - it gives your expected result exactly - obligatory SQLFiddle.
This will give you a double precision result, that you can round to whatever you want:
2 * (EXTRACT(HOUR FROM t) + EXTRACT(MINUTE FROM t) / 60) + 1
EDIT:
Or, as #CraigRinger suggested:
EXTRACT(EPOCH FROM t) / 1800 + 1
For the later, t needs to be TIME, not TIMESTAMP. Use cast if needed.
UPDATE: This will work with INTERVALs too.
SELECT 2 * (EXTRACT(HOUR FROM t) + EXTRACT(MINUTE FROM t) / 60) + 1,
EXTRACT(EPOCH FROM t) / 1800 + 1
FROM (VALUES (time '4:30:00'), (time '7:24:31'), (time '8:15:00')) as foo(t)
-- results:
?column? | ?column?
---------+---------
10 | 10
15.8 | 15.8172222222222
17.5 | 17.5
But as you wrote, there will be no edge cases (when the time cannot be divided with 30 minutes).
select
case
when date_time_field_of_interest::time >= '00:00:00' and date_time_field_of_interest::time < '00:30:00' then 1
when date_time_field_of_interest::time >= '00:30:00' and date_time_field_of_interest::time < '01:00:00' then 2
....
end
from your_table;

How to count the records per half hour from a period (datetimefrom and datetimeto) field?

I have a table which looks like you can see below:
Id Date ScheduledTimeFrom ScheduledTimeTo ActualTimeFrom ActualTimeTo
1 2013-01-01 1899-12-30 07:00:00 1899-12-30 18:00:00 1899-12-30 07:23:00 1899-12-30 17:15:00
I need to calculate per half hour how many records exists, the output should be like:
Time Actual Count:
7:00 4
7:30 4
8:00 4
8:30 4
9:00 4
9:30 5
10:00 5
10:30 6
11:00 7
11:30 8
12:00 8
12:30 8
13:00 8
13:30 8
14:00 8
14:30 8
15:00 7
15:30 7
16:00 7
16:30 6
17:00 5
17:30 4
18:00 4
I already tried to make a helper table which should hold the times per halfhour. I have joined this helpertable with the table that contains the data and after that I tried to use a group by function but it was not working.
My query was like:
Create table period (timefrom datetime, timeto datetime)
insert into period
select '1899-12-30 07:00:00.000', '1899-12-30 07:30:00.000'
Union all
select '1899-12-30 07:30:00.000', '1899-12-30 08:00:00.000'
select *
from period p left join table1 t on t.ActualTimeFrom < p.timeto and t.ActualTimeTo >=p.timefrom
Grouping this give me no desired result....
Anyone an idea how to come to the result?
P.s. I am using sql server 2005.
After snooping around and testing it on my side, looks like this date function could be the answer:
DATEADD(mi,DATEDIFF(mi,0,YOUR_DATE_COLUMN)/30*30,0)

PostgreSQL - Query a table that stores value changes and present output in a periodic format

Given the following table that stores value changes of a variable:
Timestamp Value
13:14 12
14:25 33
15:13 24
15:41 48
16:31 54
17:00 63
19:30 82
22:30 13
I need to construct a query that outputs the following:
Timestamp Value
14:00 12
15:00 33
16:00 48
17:00 63
18:00 63
19:00 63
20:00 82
21:00 82
22:00 82
23:00 13
And so on...
What would be the correct approach to achieve the desired output?
Thanks in advance.
use date_trunc() and date/time operator
roundup example
user=# select datetime from tbl_test limit 1;
datetime
------------------------
2013-07-26 15:36:00+09
(1 row)
user=# select date_trunc('hour', datetime) + interval '1 hour'
from tbl_test limit 1
?column?
------------------------
2013-07-26 16:00:00+09
(1 row)
formatting example
user=# select to_char(date_trunc('hour', datetime) + interval '1 hour', 'HH24:MI')
from tbl_test limit 1;
to_char
---------
16:00
(1 row)
UPDATED:
you can select latest one using window function.
SELECT DISTINCT x.timestamp, last_value(x.value) OVER (PARTITION BY x.timestamp)
FROM (SELECT TO_CHAR(date_trunc('hour', timestamp) + INTERVAL '1 hour', 'HH24:MI') AS timestamp, value
FROM tbl_test) as x
ORDER BY x.timestamp;
postgresql reference:
9.9. Date/Time Functions and Operators
9.8. Data Type Formatting Functions