convert datediff minutes to 100 base format in sql - sql

I want to calculate date time difference between two dates but the minutes should be in .100 scale i.e if date time difference is 2.30 (2 Hours 30 Minutes) i want it in format 2.50
30 minutes = 0.50
i wrote a query for it but it does not work well when minutes are in range of 01 - 09
Case 1 : Wrong Output
Declare #Start DateTime='02-03-2014 14:25:00'
Declare #End DateTime='02-03-2014 20:29:46'
Select STR(DateDiff(MINUTE,#Start,#End)/60)+'.'+STR(DateDiff(MINUTE,#Start,#End)%60/0.6)
DateTime Difference : 6.04
Expected Output : 6.10
Actual Output : 6.7
Case 2 : Correct Output
Declare #Start DateTime='02-03-2014 13:55:02'
Declare #End DateTime='02-03-2014 17:33:31'
Select STR(DateDiff(MINUTE,#Start,#End)/60)+'.'+STR(DateDiff(MINUTE,#Start,#End)%60/0.6)
DateTime Difference : 3.38
Expected Output : 6.63
Actual Output : 6.63
what i am missing in case, when minutes are less than 10 ??
DB : SQL Server 2008

60 minutes = 60/60 = 1.0
30 minutes = 30/60 = 0.5
4 minutes = 4/60 = 0.066, not 0.10
0.10 = 6 minutes, not 4 minutes difference as in your first example.
If we temporarily remove the seconds to reduce complexity, then you simply divide the seconds by 3600.00:
Declare #Start DateTime='02-03-2014 14:25:00'
Declare #End DateTime='02-03-2014 20:29:00'
SELECT DATEDIFF(s,#Start,#End)/3600.00
This returns 6.066 which is the correct portion of hours to return 6 hours 4 minutes difference and a far simpler expression.

Try this, it should give a very exact result(after rounding):
Declare #Start DateTime='02-03-2014 13:55:02'
Declare #End DateTime='02-03-2014 17:33:31'
Select round(cast(#end-#start as float)*24, 2)
use this if you want to round down
Select floor(cast(#end-#start as float)*2400) / 100

My friend following is tabular presentation of you requirement.
1 1.666666667
2 3.333333333
3 5
4 6.666666667
5 8.333333333
6 10
7 11.66666667
8 13.33333333
9 15
10 16.66666667
11 18.33333333
12 20
13 21.66666667
14 23.33333333
15 25
16 26.66666667
17 28.33333333
18 30
19 31.66666667
20 33.33333333
21 35
22 36.66666667
23 38.33333333
24 40
25 41.66666667
26 43.33333333
27 45
28 46.66666667
29 48.33333333
30 50
31 51.66666667
32 53.33333333
33 55
34 56.66666667
35 58.33333333
36 60
37 61.66666667
38 63.33333333
39 65
40 66.66666667
41 68.33333333
42 70
43 71.66666667
44 73.33333333
45 75
46 76.66666667
47 78.33333333
48 80
49 81.66666667
50 83.33333333
51 85
52 86.66666667
53 88.33333333
54 90
55 91.66666667
56 93.33333333
57 95
58 96.66666667
59 98.33333333
60 100
In First Case you actual difference is 6 hours & 4 Minutes. So as per requirement ans of 6.07 is correct how you are saying it is wrong?

It seems in STR(DateDiff(MINUTE,#Start,#End)%60/0.6) 0.6 should be replaced with 6.0
The above solution would round off upto 1 place after decimal.
If you want to ROUND off to 2 places after decimal you can try the below snippet:
SELECT CAST(CAST(ROUND(DateDiff(MINUTE,#Start,#End)%60/0.6) AS NUMERIC(12,2)) AS VARCHAR(50))

Related

SQL percentage calculation over the hour

I have a table consisting of thousands of devices similar to the one below, and I want to calculate the time spent by the devices in certain locations as a percentage on an hourly basis using this table.
(Values are given as an example.)
device
geohash
gridtype
total_hour_count
total_day_count
avg_spent_hour
67a47cd76baff7e2
sxk9g3
Work
500
25
20.00
67a47cd76baff7e2
swy9g3
Home
590
27
18.00
67a47cd76baff7e2
szbvfd
Other
420
18
9.28
02d171810d7ae1f5
swdvdf
Home
274
30
18,54
02d171810d7ae1f5
sdefvx
Work
184
22
17,51
02d171810d7ae1f5
dfvcxv
Other
122
19
14,12
...
...
...
...
...
...
As an example the desired output:
deviceid
home_percent
work_percent
other_percent
67a47cd76baff7e2
35
35
30
02d171810d7ae1f5
50
25
25
784faeff1c8b76c1
90
5
5
28fa9ca3dfff8a6f
80
10
10
f2f6324d5149e336
80
0
20
d84410d139981c19
25
50
25
...
...
...
...
Thanks for your help.

How to I count a range in sql?

I have a data that looks like this:
$ Time : int 0 1 5 8 10 11 15 17 18 20 ...
$ NumOfFlights: int 1 6 144 91 504 15 1256 1 1 578 ...
Time col is just 24hr time. From 0 up all the way until 2400
What I hope to get is:
hour | number of flight
-------------------------------------
1st | 240
2nd | 223
... | ...
24th | 122
Where 1st hour is from midnight to 1am, and 2nd is 1am to 2am, and so on until finally 24th which is from 11pm to midnight. And number of flights is just the total of the NumOfFlights within the range.
I've tried:
dbGetQuery(conn,"
SELECT
flights.CRSDepTime AS Time,
COUNT(flights.CRSDepTime) AS NumOnTimeFlights
FROM flights
GROUP BY CRSDepTime/60
")
But I realise it can't be done this way. The results that I get will have 40 values for time.
> head
Time NumOnTimeFlights
1 50 6055
2 105 2383
3 133 674
4 200 446
5 245 266
6 310 34
> tail
Time NumOnTimeFlights
35 2045 48136
36 2120 103229
37 2215 15737
38 2245 36416
39 2300 15322
40 2355 8018
If your CRSDepTime column is an integer encoded time like HHmm then CRSDepTime/100 will extract the hour.
SELECT
CRSDepTime/100 AS hh,
COUNT(flights.CRSDepTime) AS NumOnTimeFlights
FROM flights
GROUP BY CRSDepTime/100

Display rows where multiple columns are different

I have data that looks like this. Thousands of rows returned, but this is just a sample.
Most days have the same numbers in them, but some do not. Note that ID 1 and 5 have identical numbers every day.
ID
Sunday
Monday
Tuesday
Wednesday
Thursday
Friday
Saturday
1
26
26
26
26
26
26
26
2
44
44
30
30
44
44
44
3
55
55
55
55
80
90
55
4
12
12
43
43
43
43
43
5
36
36
36
36
36
36
36
I'd like to only return rows where the days of the week have different numbers.
In this case, the only IDs returned should be 2, 3 & 4.
What would I want this query to look like?
Thanks!
One idea that should work in most RDBMS (with some syntax tweaks) is the following.
This is SQL Server compatible: pivot the days into rows and count the distinct values and filter accordingly:
select id
from t
cross apply (
select Count(distinct d) from (
values(sunday),(monday),(tuesday),(wednesday),(thursday),(friday),(saturday)
)d(d)
)d(v)
where d.v>1

sql sum with separate column for each day

My current code looks like this:
declare #start datetime
declare #end datetime
set #start = '2/16/2020'
set #end = '2/19/2020'
select
s.location, s.department, s.position, SUM(s.hours)/60
from SCHEDULES s where SCHDATE between #start and #end
group by s.location, s.department, s.position
It yields the following results (which is correct):
loc dep pos hrs
2 2 7 96
3 2 11 96
2 2 13 192
3 2 5 96
3 1 4 228
How do I break this out by day so that the format looks like below:
'start' is the #start variable and 'start+1' is simply that plus 1 day, etc.
loc dep pos start start+1 start+2 start+3
2 2 7 24 24 24 24
3 2 11 24 24 24 24
2 2 13 48 48 48 48
3 2 5 24 24 24 24
3 1 4 57 57 57 57
thanks
Sounds like you want to do a pivot:
SELECT *
FROM SCHEDULES s
PIVOT(
SUM(hours)
FOR SCHDATE IN (
[2020-2-16],
[2020-2-17],
[2020-2-18],
[2020-2-19])
) AS pivot_table;
Hopefully the dates you want to work with are fixed and known. If you need to pivot on calculated columns, things seem to get a lot more complicated. For example, see this thread.

yearly average from monthly daterange data

I have the following table in postgresql;
Value period
1 [2017-01-01,2017-02-01)
2 [2017-02-01,2017-03-01)
3 [2017-03-01,2017-04-01)
4 [2017-04-01,2017-05-01)
5 [2017-05-01,2017-06-01)
6 [2017-06-01,2017-07-01)
7 [2017-07-01,2017-08-01)
8 [2017-08-01,2017-09-01)
9 [2017-09-01,2017-10-01)
10 [2017-10-01,2017-11-01)
11 [2017-11-01,2017-12-01)
12 [2017-12-01,2018-01-01)
13 [2018-01-01,2018-02-01)
14 [2018-02-01,2018-03-01)
15 [2018-03-01,2018-04-01)
16 [2018-04-01,2018-05-01)
17 [2018-05-01,2018-06-01)
18 [2018-06-01,2018-07-01)
19 [2018-07-01,2018-08-01)
20 [2018-08-01,2018-09-01)
21 [2018-09-01,2018-10-01)
22 [2018-10-01,2018-11-01)
23 [2018-11-01,2018-12-01)
24 [2018-12-01,2019-01-01)
25 [2019-01-01,2019-02-01)
26 [2019-02-01,2019-03-01)
27 [2019-03-01,2019-04-01)
28 [2019-04-01,2019-05-01)
29 [2019-05-01,2019-06-01)
30 [2019-06-01,2019-07-01)
31 [2019-07-01,2019-08-01)
32 [2019-08-01,2019-09-01)
33 [2019-09-01,2019-10-01)
34 [2019-10-01,2019-11-01)
35 [2019-11-01,2019-12-01)
36 [2019-12-01,2020-01-01)
37 [2020-01-01,2020-02-01)
38 [2020-02-01,2020-03-01)
39 [2020-03-01,2020-04-01)
40 [2020-04-01,2020-05-01)
41 [2020-05-01,2020-06-01)
42 [2020-06-01,2020-07-01)
How can I get yearly average from monthly data in postgresql?
Note: Column Value is type integer and column period is type daterange.
The expected result should be
6.5 2017
18.5 2018
30.5 2019
39.5 2020
If your periods are always taking one month, including the lower bound and excluding the upper, you could try this
select
avg(value * 1.0) as average,
extract(year from lower(period)) as year
from table
group by year