SQL Server SUM(Values) - sql

I have the following query that works perfectly well. The query sums the values in a given day.
SELECT
SUM(fldValue) AS 'kWh',
DAY(fldDateTime) AS 'Day',
MONTH(fldDateTime) AS 'Month',
YEAR(fldDateTime) AS 'Year'
FROM
[Data.tblData]
WHERE
tblData_Id IN (SELECT DISTINCT tblData_Id
FROM [Data.tblData])
GROUP BY
YEAR(fldDateTime), MONTH(fldDateTime), DAY(fldDateTime),
tblData_Id,fldDateTime
ORDER BY
YEAR(fldDateTime), MONTH(fldDateTime), DAY(fldDateTime)
The problem I have is that it sums from midnight to midnight, I need it to sum the values after midnight ( >= Midnight) then up to midnight of the next day. The reason for this is the data that comes in for a day, is always after midnight. For example the first logged data will be '2016-01-01 00:01:00', the final logged data will be '2016-01-02 00:00:00'. This is how the hardware works that sends me the data.
I would like to know how to encapsulate >= midnight to midnight in the query.
Dataset:
DateTime Value
20/03/2016 00:30 69.00
20/03/2016 01:00 69.00
20/03/2016 01:30 69.00
20/03/2016 02:00 69.00
20/03/2016 02:30 69.00
20/03/2016 03:00 69.00
20/03/2016 03:30 11.88
20/03/2016 04:00 0.52
20/03/2016 04:30 1.51
20/03/2016 05:00 2.22
20/03/2016 05:30 2.11
20/03/2016 06:00 0.05
20/03/2016 06:30 6.78
20/03/2016 07:00 14.79
20/03/2016 07:30 1.57
20/03/2016 08:00 1.51
20/03/2016 08:30 4.81
20/03/2016 09:00 0.11
20/03/2016 09:30 8.99
20/03/2016 10:00 10.06
20/03/2016 10:30 15.28
20/03/2016 11:00 3.22
20/03/2016 11:30 1.73
20/03/2016 12:00 19.10
20/03/2016 12:30 2.08
20/03/2016 13:00 2.61
20/03/2016 13:30 0.84
20/03/2016 14:00 8.65
20/03/2016 14:30 2.37
20/03/2016 15:00 16.34
20/03/2016 15:30 12.66
20/03/2016 16:00 2.64
20/03/2016 16:30 0.19
20/03/2016 17:00 3.91
20/03/2016 17:30 2.39
20/03/2016 18:00 0.57
20/03/2016 18:30 1.30
20/03/2016 19:00 5.06
20/03/2016 19:30 17.45
20/03/2016 20:00 13.04
20/03/2016 20:30 5.00
20/03/2016 21:00 7.47
20/03/2016 21:30 5.09
20/03/2016 22:00 0.33
20/03/2016 22:30 5.29
20/03/2016 23:00 15.33
20/03/2016 23:30 5.39
21/03/2016 00:00 6.74
Thank you in advance.
The expected sum output value for 20/03/2016 is: 662.98
The output table will look like:
SumValue Day Month Year Meter Id
659.18 20 3 2016 6
251.37 21 3 2016 6
279.03 22 3 2016 6
280.03 23 3 2016 6
284.22 24 3 2016 6
310.12 25 3 2016 6
320.84 26 3 2016 6
269.29 27 3 2016 6
276.11 28 3 2016 6
279.11 29 3 2016 6
The value column is the sum of the values for that day, made up of lots of individual times.

Use the below query for summing up the midnight value with previous day.
SELECT
SUM(fldValue) AS 'kWh',
CASE WHEN CONVERT(VARCHAR(8), fldDateTime, 108)='00:00:00' THEN DAY(fldDateTime)-1 ELSE DAY(fldDateTime) END AS 'Day',
MONTH(fldDateTime) AS 'Month',
YEAR(fldDateTime) AS 'Year'
FROM
Data.[tblData]
GROUP BY
YEAR(fldDateTime), MONTH(fldDateTime),CASE WHEN CONVERT(VARCHAR(8), fldDateTime, 108)='00:00:00' THEN DAY(fldDateTime)-1 ELSE DAY(fldDateTime) END
ORDER BY
YEAR(fldDateTime), MONTH(fldDateTime), CASE WHEN CONVERT(VARCHAR(8), fldDateTime, 108)='00:00:00' THEN DAY(fldDateTime)-1 ELSE DAY(fldDateTime) END
Sample output :

First, I have no idea what the WHERE clause is doing, so I'm going to remove it.
Second, don't use single quotes for column names.
Third, your GROUP BY clause is too complicated. You only need to include the unaggregated columns in the SELECT.
Finally, the key idea is to subtract one hour from the values everywhere they are used. Here is a simple method:
SELECT SUM(fldValue) AS kWh,
DAY(newdt) AS [Day],
MONTH(newdt) AS [Month],
YEAR(newdt) AS [Year]
FROM (SELECT d.*, DATEADD(hour, -1, fldDateTime) as newdt
FROM Data.tblData d
) d
GROUP BY YEAR(newdt), MONTH(newdt), DAY(newdt)
ORDER BY YEAR(newdt), MONTH(newdt), DAY(newdt)

Same answer as #Gordon but you can subtract one minute instead of one hour.
SELECT SUM(fldValue) AS kWh,
DAY(newdt) AS [Day],
MONTH(newdt) AS [Month],
YEAR(newdt) AS [Year]
FROM (SELECT d.*, DATEADD(minute, -1, fldDateTime) as newdt
FROM Data.tblData d
) d
GROUP BY YEAR(newdt), MONTH(newdt), DAY(newdt)
ORDER BY YEAR(newdt), MONTH(newdt), DAY(newdt)

declare #tempTable table ([DateTime] datetime, Value Float)
insert into #tempTable ([DateTime], [Value])
select convert(datetime,'20/03/2016 00:30',103), 69.00 union all
select convert(datetime,'20/03/2016 01:00',103), 69.00 union all
select convert(datetime,'21/03/2016 00:00',103), 6.74
select * from #tempTable
select [sum] = SUM(value), [year] = year(DT), [month] = month(DT), [day] = day(DT)
from (select Value, DT = dateadd(second, -1, [DateTime]) from #tempTable) x
group by year(DT), month(DT), day(DT)

Related

How do I retrieve data in Monday to Friday Hourly Format

I have a table that is currently in the following format
ID
Title
CreatedOn
1
Test 1
2021-04-26 08:00:00
2
Test 2
2021-04-26 10:00:00
3
Test 3
2021-04-27 09:00:00
4
Test 4
2021-04-28 14:00:00
5
Test 5
2021-04-28 16:00:00
6
Test 6
2021-04-28 12:00:00
7
Test 7
2021-04-29 13:00:00
8
Test 8
2021-04-30 06:00:00
9
Test 9
2021-05-17 10:00:00
10
Test 10
2021-05-18 19:00:00
11
Test 11
2021-05-18 23:00:00
12
Test 12
2021-05-19 16:00:00
13
Test 13
2021-05-20 07:00:00
14
Test 14
2021-05-21 14:00:00
15
Test 15
2021-05-21 10:00:00
16
Test 16
2021-04-30 10:00:00
What I would like to do is a query that would tell me how many requests have been Monday to Friday per hour. So aggregate all the data into just rows of Monday to Friday.
So the query should return
Day
Hour
Count
Monday
08:00
1
Monday
10:00
2
Tuesday
10:00
1
Tuesday
19:00
1
Tuesday
23:00
1
Wednesday
14:00
1
Wednesday
16:00
2
Wednesday
12:00
1
etc.. How do I achieve this?
So far I have the following
SELECT
DATENAME(WEEK, CreatedOn) AS Week,
DATEPART(Hour, CreatedOn) AS Hour,
COUNT(*) AS Requests
FROM [Enterprise32].[dbo].[nav_EmailEstimateRequests]
where CreatedOn > '2021-01-01'
GROUP BY DATENAME(WK, CreatedOn),DATEPART(Hour, CreatedOn)
ORDER BY DATENAME(WK, CreatedOn);
But the above query returns each week so Week 1 up until Week 21. Please guide me in the right direction.
Thank you!
You want weekday for the date part:
SELECT DATENAME(WEEKDAY, CreatedOn) AS Weekday,
DATEPART(Hour, CreatedOn) AS Hour,
COUNT(*) AS Requests
FROM [Enterprise32].[dbo].[nav_EmailEstimateRequests]
WHERE CreatedOn > '2021-01-01'
GROUP BY DATENAME(WEEKDAY, CreatedOn), DATEPART(Hour, CreatedOn), DATEPART(WEEKDAY, CreatedOn)
ORDER BY DATEPART(WEEKDAY, CreatedOn), Hour;
Note: I included DATEPART(weekday, ) in the GROUP BY, so you could use it in the ORDER BY.

Calculate number of minutes for specific day from a date range

I have a table that holds vehicle activity data. There is a start date and end date columns in the table. I wish to construct a query that will show the amount of time in minutes that each vehicle is active or working on a particular day. My problem is that the time between the start date and end date may span a number of days.
Example:
dwVehicleIDFK StartDate EndDate Minutes HrsMins
731 18/09/2019 08:00 18/09/2019 13:00 300 05:00
797 18/09/2019 08:00 18/09/2019 12:00 240 04:00
687 17/09/2019 16:00 17/09/2019 21:00 300 05:00
826 17/09/2019 16:00 17/09/2019 21:00 300 05:00
734 18/09/2019 10:00 18/09/2019 15:30 330 05:30
843 18/09/2019 14:00 18/09/2019 18:00 240 04:00
662 18/09/2019 09:00 18/09/2019 14:00 300 05:00
662 17/09/2019 09:00 17/09/2019 14:00 300 05:00
662 16/09/2019 09:00 16/09/2019 14:00 300 05:00
817 18/09/2019 14:00 19/09/2019 08:00 1080 18:00
In the data above the vehicle with the ID of 817 extends over two days. How would I get the query to return the time period for the 18/09 only or up until midnight on the 18/09?
The query to return the data above:
Select
dwVehicleIDFK,
StartDate,
EndDate,
DATEDIFF(MINUTE, Convert(DateTime, StartDate, 103),
Convert(DateTime, EndDate, 103)) as Minutes,
CONVERT(varchar(5), DATEADD(minute, DATEDIFF(minute,
Convert(DateTime, StartDate, 103),
Convert(DateTime, EndDate, 103)), 0), 114) as HrsMins
from
VehHistory
Assume you loaded the data for the specified date #Day and converted the start/end date to datetime in temp table #temp:
Select
dwVehicleIDFK,
StartDate,
EndDate,
DATEDIFF(MINUTE, CASE WHEN StartDate<#Day THEN #Day ELSE StartDate END,
CASE WHEN EndDate>DATEADD(DAY,1,#Day) THEN DATEADD(DAY,1,#Day) ELSE EndDate END) AS UsedMinutes
from #temp;

sql-server-2008 R2-split-time-intervals-given-by-starttime-endtime-at-selected-point

I have a table has following data
CREATE TABLE #TempStudentSchedulingRecord(
seq_id int identity(1,1),
Student_ID int ,
PeriodNumber int ,
CPStartTime datetime ,
CPEndTime datetime ,
DateItem datetime ,
FirstSegmentEndTime datetime,
SecondSegmentEndTime datetime
)
Now
Insert Into #TempStudentSchedulingRecord
values(2730,1,'1900-01-01 07:25:00.000','1900-01-01 08:20:00.000','2010-10-05 00:00:00.000','2015-05-27 09:45:00.000','2015-05-27 16:00:00.000')
Insert Into #TempStudentSchedulingRecord values(2730,1,'1900-01-01 08:25:00.000','1900-01-01 10:00:00.000','2010-10-05 00:00:00.000','2015-05-27 09:45:00.000','2015-05-27 16:00:00.000')
Insert Into #TempStudentSchedulingRecord values(2730,1,'1900-01-01 10:05:00.000','1900-01-01 11:35:00.000','2010-10-05 00:00:00.000','2015-05-27 09:45:00.000','2015-05-27 16:00:00.000')
Now Here The firstSegmentTime is same in all rows. I want To find The Total minutes scheduled before First segment End and classes included in first segment.
Similarly find the The Total minutes scheduled between First segment End time and second segment end time and classes included in first segment.
Here the Period 2 resides both segments.. How can I calculate total minutes scheduled before first segment and second segment.
Desired Output is
Student Period CPStartTime CPEndTime DateItem FSET SSET
2730 1 01/01/00 08:25 AM 01/01/00 10:00 AM 10/05/10 12:00 AM 05/27/15 09:45 AM 05/27/15 04:00 PM
2730 2 01/01/00 08:25 AM 05/27/15 09:45 AM 10/05/10 12:00 AM 05/27/15 09:45 AM 05/27/15 04:00 PM
2730 2 05/27/15 09:45 AM 01/01/00 10:00 AM 10/05/10 12:00 AM 05/27/15 09:45 AM 05/27/15 04:00 PM
2730 3 01/01/00 10:05 AM 01/01/00 11:35 AM 10/05/10 12:00 AM 05/27/15 09:45 AM 05/27/15 04:00 PM

SQL code for Comparing date fields in different rows and combining the results

I need help for proper Oracle SQL code to combine rows for a crystal reports command object. This is a part of the bigger query I'm working on and got stuck for the past couple of days.
for eg. if the columns are like below
PatId In_time Out_time
151 01/01/2012 07:00:00 am 01/01/2012 10:00:00 am
151 01/01/2012 11:00:00 am 01/02/2012 08:00:00 am
151 01/02/2012 11:00:00 am 01/02/2012 01:00:00 pm
151 01/03/2012 08:00:00 am 01/03/2012 03:00:00 pm
151 01/06/2012 03:30:00 pm 01/09/2012 07:00:00 am
167 01/03/2012 01:30:00 pm 01/09/2012 07:00:00 am
167 01/13/2012 03:30:00 pm 01/14/2012 07:00:00 am
167 01/14/2012 11:30:00 am 01/15/2012 11:30:00 am
167 01/18/2012 12:00:00 pm 01/19/2012 03:00:00 am
Within a PatId, the code should compare the Out_time of one row to the In_time of the next row, and check whether the time gap is greater than 48 hours. If not, then it is considered part of the same visit. I want one result row per PatID & visit, with min(In_time) and max(Out_time). The time span of the visit (result row) itself may be greater than 48 hours.
For this example, for PatId 151 the time difference between the out_time of 1st row and In_time of 2nd row is less than 48 hours. The difference between Out_time of second row and In_time of 3rd row, as well as between the 3rd and 4th rows, is also less than 48 hours. After this the gap between Out_time of the 4th row and In_time of 5th row is greater than 48 hours. The result for PatId 151 should be as below and same for EmpId 167, the chaining should continue until a gap greater than 48 hours is found.
So the result for the above table should be displayed as,
PatId In_time Out_time
151 01/01/2012 07:00:00 am 01/03/2012 03:00:00 pm
151 01/06/2012 03:30:00 pm 01/09/2012 07:00:00 am
167 01/03/2012 01:30:00 pm 01/09/2012 07:00:00 am
167 01/13/2012 03:30:00 pm 01/15/2012 11:30:00 am
167 01/18/2012 12:00:00 pm 01/19/2012 03:00:00 am
I could not get the logic on how to compare and merge rows.
Thanks in Advance, Abhi
General example of subtracting time - copy/paste to see the output. This example will give you differences in hours, minutes, seconds between two dates. The basic formula is (end_date - start_date) * 86400 (number of seconds in 24 hrs)...:
SELECT trunc(mydate / 3600) hr
, trunc(mod(mydate, 3600) / 60) mnt
, trunc(mod(mydate, 3600) / 60 /60) sec
FROM
(
SELECT (to_date('01/03/2012 10:00:00', 'mm/dd/yyyy hh24:mi:ss') -
to_date('01/01/2012 07:00:00', 'mm/dd/yyyy hh24:mi:ss')) * 86400 mydate
FROM dual
)
/
HR | MNT | SEC
---------------
51 | 0 | 0
You need to check your example and logic. I could not understand what needs to be comnpared with what...

Group by values from 4 a.m to 4 a.m SQL Server

I have data from 04/01/2012 00:00 to 05/01/2012 05:00
let say
StartDate Value
04/01/2012 00:00 10
04/01/2012 05:00 10
04/01/2012 08:00 10
05/01/2012 01:00 10
05/01/2012 04:00 10
05/01/2012 05:00 10
if I do a group by date
SUM(Value)...
GROUP BY YEAR(StartDate), MONTH(StartDate),DAY(StartDate)
this group data from 04/01/2012 00:00 to 05/01/2012 00:00 and sum the full day value i.e 30
but I need to group by different time
i.e 04/01/2012 04:00 to 05/01/2012 04:00 so that the result will be 40
how to achieve this. Anyone did this before...
SUM(Value)
...
GROUP BY CAST(DATEADD(hour, -4, MyDateCol) AS Date)
select dateadd(hh, 4, date) as date, total from (
select
dateadd(dd, datediff(dd, 0, dateadd(hh, -4, startDate)), 0) as date,
sum(value) as total
from yourTable
group by dateadd(dd, datediff(dd, 0, dateadd(hh, -4, startDate)), 0)
) t
Result:
date total
2012-01-03 04:00:00.000 10
2012-01-04 04:00:00.000 30
2012-01-05 04:00:00.000 20