简体   繁体   中英

SQL Server : return distinct number of periods

We have the following SQL Server 2008 sample database table showing pay information per employee over each pay period (weekly pay so 52 or 53 weeks per year, following the UK tax year so pay period week 1 is 6th April and onwards).

I have limited the sample to one employee over a range of pay periods, the actual data goes back many years.

I am required to to produce totals for each employee for the last 12 weeks of pay from when the query is run.

+------------+------------+---------+-------+
| EMPLOYEEID | PAYELEMENT | AMOUNT  | HOURS |
+------------+------------+---------+-------+
|     160062 | 1.0 Basic  | 2724.64 |   468 |
+------------+------------+---------+-------+

However I have some issues going back 12 distinct periods due to the following...

  1. Period 1 has two entries
  2. When on holiday no period is recorded so for example week 30, 38 and 39 are missing. In this instance it needs to go back until 12 recorded periods are used.
  3. Going over the year end from period 52 to 1

I tried using the last 12 records for each employee but Item 1 above caused only 11 periods to calculate.

I have also tried using date difference on the paydate, but Item 2 above causes periods to be missing.

Do I need to add an index per employee to show 12 individual periods?

+------------+------------+------+--------+--------+-------+------+------------------+
| EMPLOYEEID | PAYELEMENT | YEAR | PERIOD | AMOUNT | HOURS | RATE |     PAYDATE      |
+------------+------------+------+--------+--------+-------+------+------------------+
|     160062 | 1.0 Basic  | 2017 |     29 | 311.22 |    39 | 7.98 | 20/10/2016 00:00 |
|     160062 | 1.0 Basic  | 2017 |     31 | 311.22 |    39 | 7.98 | 03/11/2016 00:00 |
|     160062 | 1.0 Basic  | 2017 |     32 | 311.22 |    39 | 7.98 | 10/11/2016 00:00 |
|     160062 | 1.0 Basic  | 2017 |     33 | 311.22 |    39 | 7.98 | 17/11/2016 00:00 |
|     160062 | 1.0 Basic  | 2017 |     34 | 311.22 |    39 | 7.98 | 24/11/2016 00:00 |
|     160062 | 1.0 Basic  | 2017 |     35 | 311.22 |    39 | 7.98 | 01/12/2016 00:00 |
|     160062 | 1.0 Basic  | 2017 |     36 | 183.54 |    23 | 7.98 | 08/12/2016 00:00 |
|     160062 | 1.0 Basic  | 2017 |     37 | 311.22 |    39 | 7.98 | 15/12/2016 00:00 |
|     160062 | 1.0 Basic  | 2017 |     40 | 311.22 |    39 | 7.98 | 05/01/2017 00:00 |
|     160062 | 1.0 Basic  | 2017 |     41 | 311.22 |    39 | 7.98 | 12/01/2017 00:00 |
|     160062 | 1.0 Basic  | 2017 |     42 | 311.22 |    39 | 7.98 | 19/01/2017 00:00 |
|     160062 | 1.0 Basic  | 2017 |     43 | 311.22 |    39 | 7.98 | 26/01/2017 00:00 |
|     160062 | 1.0 Basic  | 2017 |     44 | 311.22 |    39 | 7.98 | 02/02/2017 00:00 |
|     160062 | 1.0 Basic  | 2017 |     45 | 311.22 |    39 | 7.98 | 09/02/2017 00:00 |
|     160062 | 1.0 Basic  | 2017 |     46 | 311.22 |    39 | 7.98 | 16/02/2017 00:00 |
|     160062 | 1.0 Basic  | 2017 |     47 | 311.22 |    39 | 7.98 | 23/02/2017 00:00 |
|     160062 | 1.0 Basic  | 2017 |     48 | 127.68 |    16 | 7.98 | 02/03/2017 00:00 |
|     160062 | 1.0 Basic  | 2017 |     49 | 311.22 |    39 | 7.98 | 09/03/2017 00:00 |
|     160062 | 1.0 Basic  | 2017 |     50 | 247.38 |    31 | 7.98 | 16/03/2017 00:00 |
|     160062 | 1.0 Basic  | 2017 |     51 | 311.22 |    39 | 7.98 | 23/03/2017 00:00 |
|     160062 | 1.0 Basic  | 2017 |     52 | 311.22 |    39 | 7.98 | 30/03/2017 00:00 |
|     160062 | 1.0 Basic  | 2018 |      1 | 247.38 |    31 | 7.98 | 06/04/2017 00:00 |
|     160062 | 1.0 Basic  | 2018 |      1 |      0 |     0 | 7.75 | 06/04/2017 00:00 |
|     160062 | 1.0 Basic  | 2018 |      2 | 311.22 |    39 | 7.98 | 13/04/2017 00:00 |
|     160062 | 1.0 Basic  | 2018 |      3 | 255.36 |    32 | 7.98 | 20/04/2017 00:00 |
|     160062 | 1.0 Basic  | 2018 |      4 | 247.38 |    31 | 7.98 | 27/04/2017 00:00 |
|     160062 | 1.0 Basic  | 2018 |      5 | 311.22 |    39 | 7.98 | 04/05/2017 00:00 |
|     160062 | 1.0 Basic  | 2018 |      6 | 127.68 |    16 | 7.98 | 11/05/2017 00:00 |
|     160062 | 1.0 Basic  | 2018 |      7 | 247.38 |    31 | 7.98 | 18/05/2017 00:00 |
|     160062 | 1.0 Basic  | 2018 |      8 | 277.31 | 34.75 | 7.98 | 25/05/2017 00:00 |
+------------+------------+------+--------+--------+-------+------+------------------+

You should try :

;WITH Top12Periods AS (
    SELECT TOP 12 [YEAR], [PERIOD]
    FROM @employeeTable
    GROUP BY [YEAR], [PERIOD]
    ORDER BY [YEAR] DESC, [PERIOD] DESC
)
SELECT [EMPLOYEEID], [PAYELEMENT], SUM([AMOUNT]) AS TOTAL_AMOUNT, SUM([HOURS]) AS TOTAL_HOURS, AVG([RATE]) AS AVERAGE_RATE, MIN ([PAYDATE]) [MIN_PAYDATE]
FROM @employeeTable et
    JOIN Top12Periods p ON et.[YEAR] = p.[YEAR] AND et.[PERIOD] = p.[PERIOD]
GROUP BY [EMPLOYEEID], [PAYELEMENT]

Here's another approach:

SELECT
    EmployeeID,
    PayElement,
    sum(Amount) as Amount,
    sum(Hours) as Hours
FROM
    (
    SELECT *
    ,dense_rank() OVER (PARTITION BY EmployeeId ORDER BY PayDate DESC) as rank
    FROM
        Pay
    ) ranked
WHERE
    rank <= 12
GROUP BY
    EmployeeID,
    PayElement

If your zero values cause problems here, then simply add WHERE Amount > 0 (or perhaps <> 0 ) to the inner query. Depending on your data, it's possible you'll also need to add PayElement to the Partition By clause (or the inner WHERE clause).

You can test this over at rextester.com/YDBL47689

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