SQL Server query for Total of hours across multiple rows - sql-server

I've tried to resolve this a few ways and wanting some extra help.
I'm wanting to return the same number of rows but trying to calculate the number of total hours delivered by each Employee for each service on each day.
I've added a duplicate flag but that doesn't help me to work out the max hours by the 1 employee in 1 day.
Emp Service Date Start End Hrs Duplicate Flag Flag hrs
Fred xyz 14/09/2017 8:45 15:00 6.25 1 1 6.25
Fred xyz 14/09/2017 9:00 14:15 5.25 1 0 0
Fred xyz 14/09/2017 9:00 14:15 5.25 2 0 0
Fred xyz 14/09/2017 9:00 15:00 6 1 0 0
John xyz 15/09/2017 10:00 12:00 2 1 1 2
John xyz 15/09/2017 10:00 13:00 3 1 0 0
John xyz 15/09/2017 11:00 15:00 4 1 0 0
John xyz 15/09/2017 12:00 16:00 4 1 1 4
the last 2 columns are the ones I can't quite work out how to add. I've tried Overlaps and other ANDing methods.
thanks, Dave

I think you are looking for an OVER clause. Not sure what the duplicate flag is for though? If you ignore your last three columns, assuming they are computed columns in a query, you could use...
Select
*,
sum(Hrs) over (partition by Emp, Date, Service order by Date)
From (select distinct * from your table) x
If the last three columns are actual columns in your table just replace select * in the derived table with the column names, except those three.

Related

grouping rows of common values to create a new 'group id' for each set

I am trying to achieve the below but was not able to so far, any help would be greatly appreciated.
I have this data (sorted from a query by id, anchor, date, and time) that I wish to group by common anchor :
id anchor date time 'group' (the value to get)
3 2 2019-01-01 07:00 1
4 2 2019-01-01 08:00 1
5 3 2019-01-01 15:00 2
7 3 2019-01-01 16:00 2
10 3 2019-01-01 17:00 2
I'm looking to do a query in postgres where I can select this data and foreach set of common anchors, have a 'group number'
I then need a query to sum the anchor of points of same group, example above would become:
anchor sum group
2 4 1
3 9 2
thanks!
EDIT: McNets solution works perfect,
I have another case, with below data.
The anchor repeats but after a change of anchor: they're sorted by time, first it was anchor 2, then anchor 3, then again anchor 2.
I need to group after the change (ids 11 & 12) to have a new group number in this case
id anchor date time 'group' (the value to get)
3 2 2019-01-01 07:00 1
4 2 2019-01-01 08:00 1
5 3 2019-01-01 15:00 2
7 3 2019-01-01 16:00 2
10 3 2019-01-01 17:00 2
11 2 2019-01-01 18:00 3
12 2 2019-01-01 19:00 3
We can try using ROW_NUMBER here:
SELECT
anchor,
SUM(anchor) AS sum,
ROW_NUMBER() OVER (ORDER BY anchor) AS "group"
FROM yourTable
GROUP BY
anchor;
Demo

SSRS - Using specific Row Number

I have a SQL query where I am getting the row number for a count of employees per division and per month at the beginning of the month and the end of the month. To do that, I use a payroll end date which is a weekly date. So in essence I have 4 dates where employee counts are shown. Some months have 5 dates which makes the row count for that month 5 instead of 4.
I then need to build an SSRS report to show only the first employee count and the last employee count per division, per month. I have the first number since I am using =IIF(Fields!RowNumber.Value = 1, Fields!EMPCOUNT.Value, 0)
The problem I have now is getting the last employee count where I need to conditionally select a count where row number needs to be 5 if exists or 4 if it doesn't exist. I'm not sure how to get the expression to work in SSRS. Sample data is below.
PRCo EMPCOUNT udDivision PREndDate ROWNUM Type
1 89 Civil 2018-01-06 00:00:00 1 1
1 97 Civil 2018-01-13 00:00:00 2 1
1 97 Civil 2018-01-20 00:00:00 3 1
1 97 Civil 2018-01-27 00:00:00 4 1
1 16 Colorado 2018-01-06 00:00:00 1 1
1 18 Colorado 2018-01-13 00:00:00 2 1
1 14 Colorado 2018-01-20 00:00:00 3 1
1 10 Colorado 2018-01-27 00:00:00 4 1
1 94 Civil 2018-02-03 00:00:00 1 2
1 91 Civil 2018-02-10 00:00:00 2 2
1 92 Civil 2018-02-17 00:00:00 3 2
1 91 Civil 2018-02-24 00:00:00 4 2
1 16 Colorado 2018-02-03 00:00:00 1 2
1 16 Colorado 2018-02-10 00:00:00 2 2
1 18 Colorado 2018-02-17 00:00:00 3 2
1 19 Colorado 2018-02-24 00:00:00 4 2
1 92 Civil 2018-03-03 00:00:00 1 3
1 91 Civil 2018-03-10 00:00:00 2 3
1 88 Civil 2018-03-17 00:00:00 3 3
1 92 Civil 2018-03-24 00:00:00 4 3
1 90 Civil 2018-03-31 00:00:00 5 3
1 19 Colorado 2018-03-03 00:00:00 1 3
1 26 Colorado 2018-03-10 00:00:00 2 3
1 25 Colorado 2018-03-17 00:00:00 3 3
1 27 Colorado 2018-03-24 00:00:00 4 3
1 24 Colorado 2018-03-31 00:00:00 5 3
I would do this in your query rather than trying to get it to work directly in SSRS. There might be a simpler way than this but this is just based on your existing query.
Please note this is untested and just off the top of my head so it may need some editing before it will work.
SELECT * INTO #t FROM YOUR_EXISTING_QUERY
SELECT DISTINCT
PRCo
, udDivision
, YEAR(PREndDate) AS Yr
, MONTH(PREndDate) AS Mnth
, FIRST_VALUE(EMPCOUNT) OVER(PARTITION BY PRCo, udDivision, YEAR(PREndDate), MONTH(PREndDate) ORDER BY ROWNUM) AS OpeningEMPCOUNT
, LAST_VALUE(EMPCOUNT) OVER(PARTITION BY PRCo, udDivision, YEAR(PREndDate), MONTH(PREndDate) ORDER BY ROWNUM) AS CLosing_EMPCOUNT
FROM #t
Yo might need to include Type not sure what this does but you get the idea hopefully.
The FIRST_VALUE and LAST_VALUE functions simply get the first/last value within the partition defined, in your case PRCo, udDivision and then just the year and month portion of the payroll end date, the first and last positions are determined by the order clause, in this case row number.

Sql-Get time ranges from million+ rows for particular condition

I am working with SQL Server 2012, I have a table with approx 35 column and 10+ million rows.
I need to find time ranges from across the data where the value of any particular column is matching
E.g.
The sample data is as below
Datetime col1 col2 col3
2018-05-31 0:00 1 2 1
2018-05-31 13:00 2 2 2
2018-05-31 14:30 3 2 1
2018-05-31 15:00 4 3 1
2018-05-31 16:00 4 5 1
2018-05-31 17:00 3 2 2
2018-05-31 17:30 3 2 4
2018-05-31 18:00 2 2 4
2018-05-31 20:00 1 2 6
2018-05-31 21:00 2 2 3
2018-05-31 21:10 2 2 1
2018-05-31 22:00 1 6 3
2018-05-31 22:00 4 5 1
2018-05-31 23:59 4 7 2
Find the time range from data where col2 value =< 2, accordingly my expected result set is as below
Start Time End time Time Diff
2018-05-31 0:00 2018-05-31 14:30 14:30:00
2018-05-31 17:00 2018-05-31 21:10 4:10:00
I can achieved the same with below logic, but it's extremely slow
I get all rows and then
Order by date_Time
Scan the rows get the first row where exactly value is matching and record that timestamp as start time.
Scan further rows till i get the row where condition is breaking and record that timestamp as end time.
But as i have to play with huge no. Of rows, overall this will make my operation slow, any inputs or pseudo code to improve the same.
We can use a slightly modified difference in row number method here. The purpose of the first CTE labelled cte1 is to add a computed column which labels islands we want, having a col2 values <= 2, as 1 and everything else as 0. Then, we can compute the difference of two row numbers, and aggregate over the islands to find the starting and ending times, and the difference between those times.
WITH cte1 AS (
SELECT *,
CASE WHEN col2 <= 2 THEN 1 ELSE 0 END AS class
FROM yourTable
),
cte2 AS (
SELECT *,
ROW_NUMBER() OVER (ORDER BY Datetime) -
ROW_NUMBER() OVER (PARTITION BY class ORDER BY Datetime) rn
FROM cte1
)
SELECT
MIN(Datetime) AS [Start Time],
MAX(Datetime) AS [End Time],
CONVERT(TIME, MAX(Datetime) - MIN(Datetime)) AS [Time Diff]
FROM cte2
WHERE class = 1
GROUP BY rn
ORDER BY MIN(Datetime);
Demo

How to compute a grouped, running calculation in SQL

I have records like below.
Employee DateTime Project HoursWorked
Ralph 10/19/16 7:00 A 5
Ralph 10/19/16 12:00 B 5
Ralph 10/19/16 17:00 C 5
Betty 10/19/16 8:00 A 9
Betty 10/20/16 9:00 A 6
Betty 10/20/16 15:00 B 3
I need to compute Regular Hours and OT Hours.For each employee, for each day, in datetime order, the first 8 hours are Regular Hours, then they are OT Hours.Note: Project does NOT come into use for this computation; it explains why there can be multiple time entries per day.
Desired output:
Employee DateTime Project HoursWorked RegHrs OTHrs
Ralph 10/19/16 7:00 A 5 5 0
Ralph 10/19/16 12:00 B 5 3 2
Ralph 10/19/16 17:00 C 5 0 5
Betty 10/19/16 8:00 A 9 8 1
Betty 10/20/16 9:00 A 6 6 0
Betty 10/20/16 15:00 B 3 2 1
How do I write SQL to do this? I am guesing that this will require a cursor, but I have no experience writing such.
Thank you

Read next record?

We are on MS SQL-Server 2012.Users want to know if the time of the patients next admission date is less than 30 days for any reason. Doesn’t have to be seen by same provider
I am not sure how to read the next record, if the MRN ID is the same, then calculate the difference in days between the record you are on and the next next record.
For example:
Record 1 : MRNID =33 Discharge date = 1/1/2016
Record 2 : MRNID = 33 Admission date = 2/2/2016
MRNIDs are the same, so I calculate. Then I compare record 2 to record 3 and do the same process.
Use Lead() window function
select mrnid,
admission_date,
discharge_date,
lead(admission_date) over (partition by mrnid order by admission_date) next_date
from table;
SAMPLE OUTPUT
mnrid admission_date lead(admission_date)
33 2016-01-01 2016-01-02
33 2016-01-02 2016-01-03
33 2016-01-03 2016-01-04
33 2016-01-04 null
34 2016-01-01 2016-01-02
34 2016-01-02 2016-01-03
34 2016-01-03 2016-01-04
34 2016-01-04 null

Resources