简体   繁体   中英

SQL SUM hours by week across number of years

I have a table in a SQL database that holds information about the hours worked by employees across a number of years. Each employee can have more than one record for a specific date and each employees start date can be different.

I am trying to sum the weekly hours of each employee based on their first week. So if the employee started on the 17/04/2018 any hours logged in this week would be considered week 1 for this employee and the following week would be week two etc. For another employee week one could start in a different day/month/year etc.

My data includes the following fields:

Sequence_ID: relates to an individual employee

Date_European: relates to each date an employee has logged hours with the minimum of this being the first date the employee started in the company

Hours: The amount of hours logged

I also have a year field in the data which is the year of the Date_European column.

The below is what I have attempted but I know it isn't even close to the format I need.

select 
    Sequence_ID
    ,DATEPART(week,Date_European) AS Week
    ,DATEPART(year,Date_European) AS Year
    ,SUM([Hours]) AS Weekly_Hours
from [AB_DCU_IP_2018].[dbo].[mytable]
group by 
    Sequence_ID
    ,DATEPART(week,Date_European)
    ,DATEPART(year,Date_European)
order by 
    Sequence_ID
    ,DATEPART(week,Date_European)
    ,DATEPART(year,Date_European)

I tried to create the 'Week' field. From the above code it just gives me what week of a particular year a date relates to. I then added the 'Year' column to distinguish between different years, but again this only gives me what particular year that is.

Is there any way to create a 'Week' field in the format I am looking for? (Week of earliest date and surrounding dates would be week 1).

I was attempting to use the rank and partition by function by couldn't get this to work properly.

Any help would be greatly appreciated as I have been searching for a solution for hours.

Thanks in advance.

EDIT: How to create the initial table

CREATE TABLE mytable(Sequence_ID   VARCHAR(6) NOT NULL ,Date_European DATE NOT NULL ,Hours NUMERIC(5,1) NOT NULL);

INSERT INTO mytable(Sequence_ID,Date_European,Hours) VALUES ('da6Wrw','09/05/2016',7.3);
INSERT INTO mytable(Sequence_ID,Date_European,Hours) VALUES ('da6Wrw','09/06/2016',7.3);
INSERT INTO mytable(Sequence_ID,Date_European,Hours) VALUES ('da6Wrw','09/07/2016',7.3);
INSERT INTO mytable(Sequence_ID,Date_European,Hours) VALUES ('da6Wrw','09/08/2016',7.3);
INSERT INTO mytable(Sequence_ID,Date_European,Hours) VALUES ('da6Wrw','09/09/2016',7.3);
INSERT INTO mytable(Sequence_ID,Date_European,Hours) VALUES ('da6Wrw','09/12/2016',7.3);
INSERT INTO mytable(Sequence_ID,Date_European,Hours) VALUES ('da6Wrw','09/13/2016',7.3);
INSERT INTO mytable(Sequence_ID,Date_European,Hours) VALUES ('da6Wrw','09/14/2016',7.3);
INSERT INTO mytable(Sequence_ID,Date_European,Hours) VALUES ('da6Wrw','09/15/2016',7.3);
INSERT INTO mytable(Sequence_ID,Date_European,Hours) VALUES ('da6Wrw','09/16/2016',7.3);
INSERT INTO mytable(Sequence_ID,Date_European,Hours) VALUES ('da6Wrw','09/19/2016',7.3);
INSERT INTO mytable(Sequence_ID,Date_European,Hours) VALUES ('da6Wrw','09/20/2016',7.3);
INSERT INTO mytable(Sequence_ID,Date_European,Hours) VALUES ('da6Wrw','09/21/2016',7.3);
INSERT INTO mytable(Sequence_ID,Date_European,Hours) VALUES ('da6Wrw','09/22/2016',7.3);
INSERT INTO mytable(Sequence_ID,Date_European,Hours) VALUES ('da6Wrw','09/23/2016',7.3);
INSERT INTO mytable(Sequence_ID,Date_European,Hours) VALUES ('da6Wrw','09/26/2016',7.3);
INSERT INTO mytable(Sequence_ID,Date_European,Hours) VALUES ('da6Wrw','09/27/2016',7.3);
INSERT INTO mytable(Sequence_ID,Date_European,Hours) VALUES ('da6Wrw','09/28/2016',7.3);
INSERT INTO mytable(Sequence_ID,Date_European,Hours) VALUES ('da6Wrw','09/29/2016',7.3);
INSERT INTO mytable(Sequence_ID,Date_European,Hours) VALUES ('da6Wrw','09/30/2016',7.3);

What I want as the desired outcome:

| Sequence_ID | Date_European | DATEPART(week,Date_European) | Hours | Desired_OutCome_Week |
| da6Wrw      | 05/09/2016    |                           37 |   7.3 |                    1 |
| da6Wrw      | 06/09/2016    |                           37 |   7.3 |                    1 |
| da6Wrw      | 07/09/2016    |                           37 |   7.3 |                    1 |
| da6Wrw      | 08/09/2016    |                           37 |   7.3 |                    1 |
| da6Wrw      | 09/09/2016    |                           37 |   7.3 |                    1 |
| da6Wrw      | 12/09/2016    |                           38 |   7.3 |                    2 |
| da6Wrw      | 13/09/2016    |                           38 |   7.3 |                    2 |
| da6Wrw      | 14/09/2016    |                           38 |   7.3 |                    2 |
| da6Wrw      | 15/09/2016    |                           38 |   7.3 |                    2 |
| da6Wrw      | 16/09/2016    |                           38 |   7.3 |                    2 |
| da6Wrw      | 19/09/2016    |                           39 |   7.3 |                    3 |
| da6Wrw      | 20/09/2016    |                           39 |   7.3 |                    3 |
| da6Wrw      | 21/09/2016    |                           39 |   7.3 |                    3 |
| da6Wrw      | 22/09/2016    |                           39 |   7.3 |                    3 |
| da6Wrw      | 23/09/2016    |                           39 |   7.3 |                    3 |
| da6Wrw      | 26/09/2016    |                           40 |   7.3 |                    4 |
| da6Wrw      | 27/09/2016    |                           40 |   7.3 |                    4 |
| da6Wrw      | 28/09/2016    |                           40 |   7.3 |                    4 |
| da6Wrw      | 29/09/2016    |                           40 |   7.3 |                    4 |
| da6Wrw      | 30/09/2016    |                           40 |   7.3 |                    4 |
Set DateFirst 1

select 
    Sequence_ID,
    (datediff(day , DQ.WeekStarted, Date_European) / 7 + 1) EmployeeWeekNumber
    ,SUM([Hours]) AS Weekly_Hours
--into [AB_DCU_IP_2018].[dbo].[Weekly_Work_Hours_Employee]
from [AB_DCU_IP_2018].[dbo].[All_IPower_HR_Assurance_4]
CROSS APPLY (SELECT DATEADD(day, -1 * (datepart(weekday,start_date) % 7), start_date)  AS WeekStarted   
                                    FROM YourTable 
                                    WHERE <condition  to get the start_date you need>
            ) DQ
group by 
    Sequence_ID,
   (datediff(day , DQ.WeekStarted, Date_European) / 7 + 1)
order by 
    Sequence_ID
    ,DATEPART(week,Date_European)
    ,DATEPART(year,Date_European)

Here is another approach using the sample data you posted.

select mt.Sequence_ID
    , mt.Date_European 
    , DATEPART(week, mt.Date_European) 
    , mt.Hours
    , MyRow.GroupNum
from  mytable mt
join
(
    select WeekNum = DATEPART(week,Date_European) 
        , GroupNum = ROW_NUMBER() over(order by DATEPART(week,Date_European))
    from  mytable
    group by DATEPART(week,Date_European) 

) MyRow on MyRow.WeekNum = DATEPART(week, mt.Date_European) 

try this

select *,rn-1 [Employee_week] from (
select *,dense_RANK() over(Partition by Sequence_ID order by iif(weekly_hours=0,0,week) ) [rn] from (
select 
    Sequence_ID
    ,DATEPART(week,Date_European) AS Week
    ,DATEPART(year,Date_European) AS Year
    ,SUM([Hours]) AS Weekly_Hours
--into [AB_DCU_IP_2018].[dbo].[Weekly_Work_Hours_Employee]
from [AB_DCU_IP_2018].[dbo].[All_IPower_HR_Assurance_4]
group by 
    Sequence_ID
    ,DATEPART(week,Date_European)
    ,DATEPART(year,Date_European)
order by 
    Sequence_ID
    ,DATEPART(week,Date_European)
    ,DATEPART(year,Date_European))a)a
    where rn = 2

This'll give you the hours each employee worked on their first week, use rn>2 to get the remaining weeks

I actually found an easier way to calculate the week number of the employee that uses the DENSE_Rank function.

I have included this below incase anyone as similar issues. I have commented out the DATEPART sections as I was only using these columns as a check to ensure it was working correctly:

select 
     Sequence_ID
    ,Date_European
    --,DATEPART(week,Date_European) AS Week
    --,DATEPART(year,Date_European) AS Year
    ,DENSE_RANK() OVER (PARTITION BY Sequence_ID ORDER BY DATEPART(year,Date_European), DATEPART(week,Date_European) asc) AS EmployeeWeekNumber
    ,Hours
from [AB_DCU_IP_2018].[dbo].[All_IPower_HR_Assurance_4]
order by 
     Sequence_ID 
    ,Date_European
    --,DATEPART(week,Date_European)
    --,DATEPART(year,Date_European) 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM