简体   繁体   中英

SQL Server : Over Partition

I am trying to get to grips with using the function Partition to generate results, unfortunately I am dealing with someone else table design that has no primary key and I am not able to add one "terrible I know"

My sample code as below

CREATE TABLE mytable  (OrderNo varchar(20), TaskNo int, Hours Decimal(2))

insert into mytable values ('GNR68003327','0001',1)
insert into mytable values ('GNR68003327','0002',2)
insert into mytable values ('GNR68003327','0002',2)
insert into mytable values ('GNR68003327','0002',2)
insert into mytable values ('GNR68003327','0003',0)
insert into mytable values ('GNR68003327','0004',0)
insert into mytable values ('GNR68003327','0005',0)
insert into mytable values ('GNR68003327','0006',0)
insert into mytable values ('GNR68003327','0007',4)
insert into mytable values ('GNR68003327','0007',4)
insert into mytable values ('GNR68003327','0007',4)
insert into mytable values ('GNR68003327','0007',4)

I know I could just use a distinct to get the following results but in this instance I am going to be better of using Partition due to this being only an example of what I am trying to do so there is some more to go with this.

What I want to do is return the first value of the Hours column at every TaskNo change so the results should be

OrderNo     TaskNo  Hours 
GRN68003327 0001    1
GRN68003327 0002    2
GRN68003327 0003    0
GRN68003327 0004    0
GRN68003327 0005    0
GRN68003327 0006    0
GRN68003327 0007    4

I think it should look something like this but I just cant get the required results

SELECT 
    OrderNo, TaskNo, 
    First_Value(Hours) OVER (PARTITION BY OrderNo ORDER BY TaskNo) 
FROM 
    mytable

If anyone could help it would be much appreciated.

Thanks Phil

You have to partition by TaskNo and OrderNo to get the results you want. Since you don't have any meaningful way to order the rows within those partitions you can just order by TaskNo , but there's no guarantee that you'll get the same "first" record every time without some sort of indicator of order:

SELECT OrderNo, 
       TaskNo, 
       First_Value(Hours) OVER (PARTITION BY OrderNo , TaskNo ORDER BY TaskNo) 
FROM mytable

You would use row_number() :

select t.*
from (select t.*,
             row_number() over (partition by orderno, taskno order by ??) as seqnum
      from mytable t
     ) t
where seqnum = 1;

Notice the ?? in the query. SQL tables represent unordered sets. There is no first or last row within a set. You need a column that specifies the ordering. Whatever that column is, use it for the ?? .

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