简体   繁体   中英

Problems using OVER PARTITION BY

I have some trouble using ROW_NUMBER() OVER (PARTITION BY ...).

I have the following table

StartTime | EndTime | ContractStart
----------+---------+--------------
10:00     |  12:00  | 2015-03-02
11:00     |  22:00  | 2014-01-02
10:00     |  12:00  | 2015-03-02
10:00     |  12:00  | 2014-01-02

The person had a work contract starting at the 2014-01-02 . Something in that contract changed and he got a new one at the 2015-03-02 . Now I want to sum up the working time for the new contract. My code is:

SELECT 
    SUM(DATEDIFF(Minute, table.StartTime, table.EndTime))
FROM
    (SELECT 
         *, 
         ROW_NUMBER() OVER (PARTITION BY ContractStart 
                            ORDER BY ContractStart DESC) AS seqnum
     FROM table) table
WHERE 
    seqnum = 1

I actually thought that the code would divide the table into two partitions. one with the data for each contract. Now every partition gets a number. Since I set ORDER BY ContractStart DESC the latest contract is in the first partition which I choose in the Where Clause of the query. My result is always 0 and I do not know what is wrong with the code. Can anyone tell what is wrong with the code and why it is not producing the result I want.

Well, you did partition the data by ContractStart , sure. But then the row number doesn't actually tell you anything useful:

StartTime|EndTime|ContractStart|seqnum
10:00    |12:00  |2015-03-02   |1
11:00    |22:00  |2014-01-02   |1
10:00    |12:00  |2015-03-02   |2
10:00    |12:00  |2014-01-02   |2

You don't actually want a windowing function - all you need is a simple group by :

select
 top 1
 sum(datediff(Minute, StartTime, EndTime))
from [table]
group by [ContractStart]
order by [ContractStart] desc

Another approach (depending on your desired output).

SELECT ContractStart, SUM(DATEDIFF(Minute, StartTime, EndTime)) AS WorkingTime
FROM yourtable
GROUP BY ContractStart

Output:

ContractStart               WorkingTime
January, 02 2014 00:00:00   780
March, 02 2015 00:00:00     240

SQL Fiddle: http://sqlfiddle.com/#!3/7d539/4/0

I'm also going to assume this would be part of a larger query (including employee id's of some sort) which could be included in the selection and group by.

Pseudo

SELECT e.id, c.ContractStart, SUM(DATEDIFF(Minute, c.StartTime, c.EndTime)) AS WorkingTime
FROM contracts c
INNER JOIN employee e ON c.employeeid = e.id
GROUP BY e.id, c.ContractStart

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