Getting a cumulative number of records within a day - sql

I am trying to get a cumulative sum of records within a time period of a day. Below is a current sample of my data.
DT No_of_records
2017-05-01 00:00:00.000 241
2017-05-01 04:00:00.000 601
2017-05-01 08:00:00.000 207
2017-05-01 12:00:00.000 468
2017-05-01 16:00:00.000 110
2017-05-01 20:00:00.000 450
2017-05-02 00:00:00.000 151
2017-05-02 04:00:00.000 621
2017-05-02 08:00:00.000 179
2017-05-02 12:00:00.000 163
2017-05-02 16:00:00.000 579
2017-05-02 20:00:00.000 299
I am trying to sum up the number of records until the day changes in another column. My desired output is below.
DT No_of_records cumulative
2017-05-01 00:00:00.000 241 241
2017-05-01 04:00:00.000 601 842
2017-05-01 08:00:00.000 207 1049
2017-05-01 12:00:00.000 468 1517
2017-05-01 16:00:00.000 110 1627
2017-05-01 20:00:00.000 450 2077
2017-05-02 00:00:00.000 151 151
2017-05-02 04:00:00.000 621 772
2017-05-02 08:00:00.000 179 951
2017-05-02 12:00:00.000 163 1114
2017-05-02 16:00:00.000 579 1693
2017-05-02 20:00:00.000 299 1992
Do any of you have ideas on how to get the cumulative column?

If 2012+ you can use with window function sum() over
Select *
,cumulative = sum(No_of_records) over (Partition by cast(DT as date) Order by DT)
From YourTable

You can do this with a windowed SUM():
Select DT, No_of_records,
Sum(No_of_records) Over (Partition By Convert(Date, DT) Order By DT) As cumulative
From YourTable

For older version use CROSS APPLY or Correlated sub-query
SELECT DT,
No_of_records,
cs.cumulative
FROM YourTable a
CROSS apply(SELECT Sum(No_of_records)
FROM YourTable b
WHERE Cast(a.DT AS DATE) = Cast(b.DT AS DATE)
AND a.DT >= b.DT) cs (cumulative)
Rextester Demo

Related

MSSQL server SQL query how to utilize "group by"

Table Data
My_table_data.
testdate plant value
2020-05-14 02:00:00.000 1 68
2020-05-14 01:00:00.000 3 115
2020-05-14 02:00:00.000 2 107
2020-05-14 03:00:00.000 2 102
2020-05-14 05:00:00.000 2 104
2020-05-14 06:00:00.000 2 111
2020-05-14 08:00:00.000 1 74
2020-05-14 08:00:00.000 2 114
2020-05-14 09:00:00.000 1 70
2020-05-14 09:00:00.000 2 114
2020-05-14 03:00:00.000 3 106
2020-05-14 03:00:00.000 3 102
2020-05-15 02:00:00.000 2 108
2020-05-14 05:00:00.000 1 74
2020-05-14 04:00:00.000 3 96
2020-05-14 04:00:00.000 3 97
2020-05-14 06:00:00.000 1 80
2020-05-14 03:00:00.000 1 77
2020-05-14 06:00:00.000 3 102
I am novice at complex SQL query phrase. How to achieve the result like below.
Conditions
1. Latest data on timestamp(Hour)
2. single row for each plant.
WITH data AS(
SELECT testdate, plant, value, (DATEPART(HOUR,testdate))AS dH FROM My_table_data
WHERE testdate >= (SELECT CONVERT(DATETIME, CONVERT(DATE, GETDATE()), 120))
)
SELECT data.testdate, data.plant, data.value from data
WHERE data.dH= (SELECT MAX(data.dH) FROM data)
GROUP BY data.plant
ORDER BY data.plant DESC;
It gives error!!
testdate Plant value
2020-05-14 09:00:00.000 1 70
2020-05-14 09:00:00.000 2 114
2020-05-14 06:00:00.000 3 102
I think this should be as simple as
with maxData
AS
(
SELECT MAX(testDate) as testDate, plantId
FROM My_table_data
GROUP BY plantId
)
select
t.testDate,
t.plantId,
t.value
from My_table_data t
INNER JOIN maxData m
on t.testDate = m.testDate
and t.plantId = m.plantId
order by plantId
WHat this does is uses a CTE to find the max date for every plantId and then joins that info back to the original table to find the value corresponding to that plantId and date.

Update fields in table based on previous field records

I have a table of records for pay periods with fields WeekStart and WeekEnd populated for ever fiscal year. In my application a user should be able to update the first WeekEnd date for a given fiscal year and that should in turn update subsequent records WeekStart date by adding 1 day to the Previous WeekEnd date and for the same records's WeekEnd date, add 13 days to the new WeekStart date.
This is part of a Stored Procedure written in SQL Server 2016.
UPDATE [dbo].[staffing_BiweeklyPPCopy]
SET
[WeekStart] = DATEADD(DD, 1, LAG([WeekEnd], 1) OVER (ORDER BY [ID])),
[WeekEnd] = DATEADD(DD, 14, LAG([WeekEnd], 1) OVER (ORDER BY [ID]))
WHERE
[FiscalYear] = #fiscalyear
Original Table contents shown below...
ID WeekStart WeekEnd
163 2018-10-01 2018-10-13
164 2018-10-14 2018-10-27
165 2018-10-28 2018-11-10
166 2018-11-11 2018-11-24
167 2018-11-25 2018-12-08
168 2018-12-09 2018-12-22
169 2018-12-23 2019-01-05
170 2019-01-06 2019-01-19
171 2019-01-20 2019-02-02
172 2019-02-03 2019-02-16
173 2019-02-17 2019-03-02
174 2019-03-03 2019-03-16
175 2019-03-17 2019-03-30
176 2019-03-31 2019-04-13
177 2019-04-14 2019-04-27
178 2019-04-28 2019-05-11
179 2019-05-12 2019-05-25
180 2019-05-26 2019-06-08
181 2019-06-09 2019-06-22
182 2019-06-23 2019-07-06
183 2019-07-07 2019-07-20
184 2019-07-21 2019-08-03
185 2019-08-04 2019-08-17
186 2019-08-18 2019-08-31
187 2019-09-01 2019-09-14
188 2019-09-15 2019-09-28
189 2019-09-29 2019-09-30
For example if a user updates the weekend date for record ID 163 to '2018-10-14', the table will update as follows..
ID WeekStart WeekEnd
163 2018-10-01 2018-10-14
164 2018-10-15 2018-10-28
165 2018-10-29 2018-11-11
166 2018-11-12 2018-11-25
167 2018-11-26 2018-12-09
.
.
.
189 2019-09-30 2019-09-30
Thank you in advance.

MSSQL MAX returns all results?

I have tried the following query to return the highest P.Maxvalue for each ME.Name from the last day between 06:00 and 18:00:
SELECT MAX(P.MaxValue) AS Value,P.DateTime,ME.Name AS ID
FROM vManagedEntity AS ME INNER JOIN
Perf.vPerfHourly AS P ON ME.ManagedEntityRowId = P.ManagedEntityRowId INNER JOIN
vPerformanceRuleInstance AS PRI ON P.PerformanceRuleInstanceRowId = PRI.PerformanceRuleInstanceRowId INNER JOIN
vPerformanceRule AS PR ON PRI.RuleRowId = PR.RuleRowId
WHERE (ME.ManagedEntityTypeRowId = 2546) AND (pr.ObjectName = 'VMGuest-cpu') AND (pr.CounterName LIKE 'cpuUsageMHz') AND (CAST(p.DateTime as time) >= '06:00:00' AND CAST(p.DateTime as time) <='18:00:00') AND (p.DateTime > DATEADD(day, - 1, getutcdate()))
group by ME.Name,P.DateTime
ORDER by id
but it seems to return each MaxValue for each ID instead of the highest?
like:
Value DateTime ID
55 2018-02-19 12:00:00.000 bob:vm-100736
51 2018-02-19 13:00:00.000 bob:vm-100736
53 2018-02-19 14:00:00.000 bob:vm-100736
52 2018-02-19 15:00:00.000 bob:vm-100736
52 2018-02-19 16:00:00.000 bob:vm-100736
51 2018-02-19 17:00:00.000 bob:vm-100736
54 2018-02-19 18:00:00.000 bob:vm-100736
51 2018-02-20 06:00:00.000 bob:vm-100736
51 2018-02-20 07:00:00.000 bob:vm-100736
53 2018-02-20 08:00:00.000 bob:vm-100736
52 2018-02-20 09:00:00.000 bob:vm-100736
78 2018-02-19 12:00:00.000 bob:vm-101
82 2018-02-19 13:00:00.000 bob:vm-101
79 2018-02-19 14:00:00.000 bob:vm-101
78 2018-02-19 15:00:00.000 bob:vm-101
79 2018-02-19 16:00:00.000 bob:vm-101
77 2018-02-19 17:00:00.000 bob:vm-101
82 2018-02-19 18:00:00.000 bob:vm-101
82 2018-02-20 06:00:00.000 bob:vm-101
79 2018-02-20 07:00:00.000 bob:vm-101
81 2018-02-20 08:00:00.000 bob:vm-101
82 2018-02-20 09:00:00.000 bob:vm-101
155 2018-02-19 12:00:00.000 bob:vm-104432
there is one value per hour for each id hence twelve results for each id
does MAX not work in this way i want ?
Thanks
expected view like this :
Value DateTime ID
55 2018-02-19 12:00:00.000 bob:vm-100736
82 2018-02-19 13:00:00.000 bob:vm-101
etc
If you're using group by on datetime and id, you'll get all datetimes and all ids, it's that simple.
If you don't need exact time, you can group by date only:
SELECT MAX(P.MaxValue) AS Value, cast(P.DateTime as date) as dat, ME.Name AS ID
...
group by ME.Name, cast(P.DateTime as date)
Or if you do, you may use not exists clause instead of group by.

How do you time weight average data between two dates for any desired interval in Microsoft SQL Server 2014 Express?

I am trying to write a SQL call that will time weight average data in any desired interval. This meaning i only have to change a few parameters inside the query so the final output will be in Day's, Hours and or minutes between my two desired dates.
I also need it to fill in data between missing intervals like this Example
Actual DataBase Data
Time_Stamp Time_Stamp_ms BPS_FIT0161
2014-07-26 22:32:36 74 164
2014-07-26 22:32:37 71 164
2014-07-26 22:32:38 71 164
2014-07-26 22:32:39 70 162
2014-07-26 22:32:40 71 162
2014-07-26 22:32:41 67 162
2014-07-26 22:32:42 64 165
2014-07-26 22:32:43 63 164
2014-07-26 22:32:44 62 164
2014-07-26 22:32:45 63 163
2014-07-26 22:32:46 59 163
2014-07-26 22:32:47 56 165
2014-07-26 22:32:48 55 167
2014-07-26 22:32:49 54 167
2014-07-26 22:32:50 54 168
2014-07-26 22:32:51 51 168
2014-07-26 22:32:52 47 171
2014-07-26 22:32:53 46 173
2014-07-26 22:32:54 111 177
2014-07-26 22:32:55 42 178
2014-07-26 22:38:56 99 178
2014-07-26 23:24:57 426 178
2014-07-27 00:21:58 854 178
2014-07-27 01:53:09 229 178
2014-07-27 03:30:11 419 178
2014-07-27 05:25:14 56 178
2014-07-27 07:32:16 881 178
2014-07-27 09:48:20 48 178
2014-07-27 12:55:24 286 178
2014-07-27 16:13:28 562 178
2014-07-27 20:10:33 803 178
2014-07-28 00:56:40 26 178
2014-07-28 06:38:47 753 178
2014-07-28 08:38:47 753 178
2014-07-28 09:24:37 219 248
2014-07-28 09:24:38 218 248
2014-07-28 09:24:39 214 226
2014-07-28 09:24:40 212 226
2014-07-28 09:24:41 212 226
2014-07-28 09:24:42 208 224
2014-07-28 09:24:43 207 222
2014-07-28 09:24:44 206 222
2014-07-28 09:24:45 206 222
2014-07-28 10:11:45 604 202
SQL Time Weighted Average (TWA) Hourly query should look something like this:
Date_time BPS_FIT0161 TWA
2014-07-26 22:00:00 177.4342105
2014-07-26 23:00:00 178
2014-07-27 00:00:00 178
2014-07-27 01:00:00 178
2014-07-27 02:00:00 178
2014-07-27 03:00:00 178
2014-07-27 04:00:00 178
2014-07-27 05:00:00 178
2014-07-27 06:00:00 178
2014-07-27 07:00:00 178
2014-07-27 08:00:00 178
2014-07-27 09:00:00 178
2014-07-27 10:00:00 178
2014-07-27 11:00:00 178
2014-07-27 12:00:00 178
2014-07-27 13:00:00 178
2014-07-27 14:00:00 178
2014-07-27 15:00:00 178
2014-07-27 16:00:00 178
2014-07-27 17:00:00 178
2014-07-27 18:00:00 178
2014-07-27 19:00:00 178
2014-07-27 20:00:00 178
2014-07-27 21:00:00 178
2014-07-27 22:00:00 178
2014-07-27 23:00:00 178
2014-07-28 00:00:00 178
2014-07-28 01:00:00 178
2014-07-28 02:00:00 178
2014-07-28 03:00:00 178
2014-07-28 04:00:00 178
2014-07-28 05:00:00 178
2014-07-28 06:00:00 178
2014-07-28 07:00:00 178
2014-07-28 08:00:00 178
2014-07-28 09:00:00 179.5349202
2014-07-28 10:00:00 202.0857852
Thank you so much for your help!
http://sqlfiddle.com/#!6/a8db7/1
End of my question
Beginning of solutions
Using VKP's Solution
SELECT dateadd(hour, datediff(hour, 0, Time_Stamp),0) as Date_Time,
sum(time_stamp_ms * bps_fit0161)/sum(time_stamp_ms) as weighted_avg
FROM BPS
WHERE Time_Stamp BETWEEN CONVERT(DATETIME, '2014-07-26 00:00:00', 102)
AND CONVERT(DATETIME, '2014-07-30 00:00:00', 102)
group by dateadd(hour, datediff(hour, 0, Time_Stamp),0),
dateadd(day,datediff(day, 0, Time_Stamp),0)
order by dateadd(hour, datediff(hour, 0, Time_Stamp),0),
dateadd(day,datediff(day, 0, Time_Stamp),0)
My Query's Result
Date_Time weighted_avg
2014-07-26 00:00:00.000 180
2014-07-26 01:00:00.000 113
2014-07-26 02:00:00.000 147
2014-07-26 03:00:00.000 221
2014-07-26 04:00:00.000 252
2014-07-26 05:00:00.000 379
2014-07-26 06:00:00.000 370
2014-07-26 07:00:00.000 253
2014-07-26 08:00:00.000 125
2014-07-26 09:00:00.000 119
2014-07-26 10:00:00.000 125
2014-07-26 11:00:00.000 117
2014-07-26 12:00:00.000 160
2014-07-26 13:00:00.000 123
2014-07-26 14:00:00.000 86
2014-07-26 15:00:00.000 81
2014-07-26 16:00:00.000 100
2014-07-26 17:00:00.000 108
2014-07-26 18:00:00.000 175
2014-07-26 19:00:00.000 238
2014-07-26 20:00:00.000 211
2014-07-26 21:00:00.000 231
2014-07-26 22:00:00.000 173
2014-07-26 23:00:00.000 178
2014-07-27 00:00:00.000 178
2014-07-27 01:00:00.000 178 <----- Start of missing Data!
2014-07-27 03:00:00.000 178
2014-07-27 05:00:00.000 178
2014-07-27 07:00:00.000 178
2014-07-27 09:00:00.000 178
2014-07-27 12:00:00.000 178
2014-07-27 16:00:00.000 178
2014-07-27 20:00:00.000 178
2014-07-28 00:00:00.000 178
2014-07-28 06:00:00.000 178
2014-07-28 09:00:00.000 160
2014-07-28 10:00:00.000 134
2014-07-28 11:00:00.000 113
2014-07-28 12:00:00.000 136
2014-07-28 13:00:00.000 131
2014-07-28 14:00:00.000 84
2014-07-28 15:00:00.000 102
As you can see I am missing hours due to our database being offline or wireless nodes on my network losing communication. What would you change in the above query to auto fill missing hours with the previous hours data, the same goes for missing data for days.
http://sqlfiddle.com/#!6/a8db7/31/0
declare #s datetime
declare #e datetime
set #s = '2014-07-26 00:00:00'
set #e = '2014-07-30 00:00:00'
;with x(n) as
(
SELECT TOP (DATEDIFF(HOUR, #s, #e) + 1)
rn = ROW_NUMBER() OVER (ORDER BY [object_id])
FROM sys.all_columns ORDER BY [object_id]
)
select DATEADD(HOUR, n-1, #s) as dt into t from x
;with y as (
SELECT
row_number() over(order by t.dt) as rn,
t.dt,
sum(time_stamp_ms * bps_fit0161) / sum(time_stamp_ms) as weighted_avg
FROM BPS
right join t on t.dt = dateadd(hour, datediff(hour, 0, Time_Stamp),0)
group by t.dt,dateadd(hour, datediff(hour, 0, Time_Stamp),0)
)
select y.dt ,
case when y.weighted_avg is null then prev_y.weighted_avg
else y.weighted_avg end as weighted_avg
from y
left join y prev_y on y.rn = prev_y.rn-1
Try this. This groups by the start of any hour till the end of that hour.
Edited: To include all the hours between specified times. This may get you closer to what you are looking for.

SQL to Find records where result is in range between two columns, but check multiple rows

I'm working with two datasets, one is a more detailed view of clock punch activity, and another is a summation of entire "shifts" that these clock punches make up. What we are trying to accomplish, is to return a record where the PAYCODEID is equal to '7' or '8' (these are meal break codes), and if it falls within the range of the last two columns in the entire shift table just below:
ClockEventShifts:
ShiftID EMPID Clockin MealRangeMax
1 00001280687 2014-02-16 08:00:00.000 2014-02-16 14:00:00.000
6 00001280687 2014-02-17 16:00:00.000 2014-02-17 22:00:00.000
There are a few key possibilities for the more detailed view of clock punches:
ClockEvent A:
EVENTID EMPID CLOCKIN CLOCKOUT PAYCODEID
228 00001280687 2014-02-16 08:00:00.000 2014-02-16 12:00:00.000 20
234 00001280687 2014-02-16 12:00:00.000 2014-02-16 13:00:00.000 8
235 00001280687 2014-02-16 13:00:00.000 2014-02-16 16:00:00.000 20
237 00001280687 2014-02-16 16:00:00.000 2014-02-16 17:01:00.000 21
238 00001280687 2014-02-16 17:01:00.000 2014-02-16 18:00:00.000 20
236 00001280687 2014-02-17 16:00:00.000 2014-02-17 17:00:00.000 20
ClockEvent B:
EVENTID EMPID CLOCKIN CLOCKOUT PAYCODEID
228 00001280687 2014-02-16 08:00:00.000 2014-02-16 12:00:00.000 20
234 00001280687 2014-02-16 12:00:00.000 2014-02-16 13:00:00.000 21
235 00001280687 2014-02-16 13:00:00.000 2014-02-16 16:00:00.000 20
237 00001280687 2014-02-16 16:00:00.000 2014-02-16 17:01:00.000 8
238 00001280687 2014-02-16 17:01:00.000 2014-02-16 18:00:00.000 20
236 00001280687 2014-02-17 16:00:00.000 2014-02-17 17:00:00.000 20
ClockEvent C:
EVENTID EMPID CLOCKIN CLOCKOUT PAYCODEID
228 00001280687 2014-02-16 08:00:00.000 2014-02-16 12:00:00.000 20
234 00001280687 2014-02-16 12:00:00.000 2014-02-16 13:00:00.000 21
235 00001280687 2014-02-16 13:00:00.000 2014-02-16 16:00:00.000 20
237 00001280687 2014-02-16 16:00:00.000 2014-02-16 17:01:00.000 21
238 00001280687 2014-02-16 17:01:00.000 2014-02-16 18:00:00.000 20
236 00001280687 2014-02-17 16:00:00.000 2014-02-17 17:00:00.000 20
ClockEvent D:
EVENTID EMPID CLOCKIN CLOCKOUT PAYCODEID
228 00001280687 2014-02-16 08:00:00.000 2014-02-16 12:00:00.000 20
234 00001280687 2014-02-16 12:00:00.000 2014-02-16 13:00:00.000 8
235 00001280687 2014-02-16 13:00:00.000 2014-02-16 16:00:00.000 20
237 00001280687 2014-02-16 16:00:00.000 2014-02-16 17:01:00.000 8
238 00001280687 2014-02-16 17:01:00.000 2014-02-16 18:00:00.000 20
236 00001280687 2014-02-17 16:00:00.000 2014-02-17 17:00:00.000 20
ClockEvent E:
EVENTID EMPID CLOCKIN CLOCKOUT PAYCODEID
228 00001280687 2014-02-16 08:00:00.000 2014-02-16 12:00:00.000 8
234 00001280687 2014-02-16 12:00:00.000 2014-02-16 13:00:00.000 21
235 00001280687 2014-02-16 13:00:00.000 2014-02-16 16:00:00.000 8
237 00001280687 2014-02-16 16:00:00.000 2014-02-16 17:01:00.000 21
238 00001280687 2014-02-16 17:01:00.000 2014-02-16 18:00:00.000 20
236 00001280687 2014-02-17 16:00:00.000 2014-02-17 17:00:00.000 20
Ideally, a perfect query/sproc could return the following in each scenario, checking for punches 360 minutes out:
A:
EVENTID EMPID CLOCKIN CLOCKOUT PAYCODEID
234 00001280687 2014-02-16 12:00:00.000 2014-02-16 13:00:00.000 8
B:
Nada!
C:
Nada!
D:
EVENTID EMPID CLOCKIN CLOCKOUT PAYCODEID
234 00001280687 2014-02-16 12:00:00.000 2014-02-16 13:00:00.000 8
E (it could return multiples too, but I really only care about the existence of at least one meal before 6 hours):
EVENTID EMPID CLOCKIN CLOCKOUT PAYCODEID
228 00001280687 2014-02-16 08:00:00.000 2014-02-16 12:00:00.000 8
It could also do something like this, ignoring that MealRangeMax piece and just using Clockin from ClockEventShifts:
A:
MINUTE_DIFFERENCE
240
B:
MINUTE_DIFFERENCE
600
C:
MINUTE_DIFFERENCE
NULL
D:
MINUTE_DIFFERENCE
240
600 (optional)
E:
MINUTE_DIFFERENCE
0
300 (optional)
I would tend to use something like IN or BETWEEN for such things, but IN can't check the values between things though to my knowledge, and BETWEEN can only check against an X and Y value to my knowledge, but I need to continue those BETWEEN checks for the rest of the result set from ClockEventShifts. I'm still searching for some solutions, but this seems to be slightly more complex.
Does anyone have any advice or ideas in approaching this problem?
This sql statement will give you records from CLOCKEVENT where the paycode is 7 or 8 and the event occurs within ClockEventShifts clockin time and mealrangemax.
SELECT ce.*
FROM ClockEvent ce
, ClockEventShifts ces
WHERE ce.PAYCODEID IN(7, 8)
AND ce.EMPID = ces.EMPID
AND ce.CLOCKIN >= ces.CLOCKIN
AND ce.CLOCKOUT <= ces.MealRangeMax
If you only care about the ClockIn time being within the ClockEventShift range of time, you could use this:
SELECT ce.*
FROM ClockEvent ce
, ClockEventShifts ces
WHERE ce.PAYCODEID IN(7, 8)
AND ce.EMPID = ces.EMPID
AND ce.CLOCKIN BETWEEN ces.CLOCKIN AND ces.MealRangeMax