开发者

TSQL-Join on own table, selecting the latest row only

开发者 https://www.devze.com 2023-04-07 16:15 出处:网络
I have a table tbl_Partner (shortened) with two \"duplicate\" partners: RecordID (GUID) | RISEID (varchar(40)) | UpdateCounter(int) | etc. ...

I have a table tbl_Partner (shortened) with two "duplicate" partners:

RecordID (GUID) | RISEID (varchar(40)) | UpdateCounter(int) | etc. ...
-----------------------------------------------------------
12345678-9012-3456-7890-123456789012 | RISE123 | 0
87564321-9012-3456-7890-123456789012 | RISE123 | 1
-- other partners with different updatecounters etc.

Now I need a view which has the latest data for each partner (highest UpdateCounter) but the first RecordID (lowest UpdateCounter)

I tried this SQL already:

开发者_开发技巧select 
(select top 1 recordid from tbl_partner p2 where p2.riseid=p1.riseid order by p2.updatecounter ASC) as RecordID
, riseid, updatecounter
from tbl_partner p1
order by riseid

I get:

RecordID (GUID) | RISEID (varchar(40)) | UpdateCounter(int)
-----------------------------------------------------------
12345678-9012-3456-7890-123456789012 | RISE123 | 0 --(old data)
12345678-9012-3456-7890-123456789012 | RISE123 | 1 --(new correct data with the first RecordID)
-- other rows/columns omitted

How can I select the latest row for each RecordID/RiseID only? (UpdateCounter=1 in this example)

For the record: UpdateCounter can be something else than 1 of course and there are other datasets with different values. So I cannot use a simple WHERE updatecounter>0.


SELECT t1.RecordID,t1.RISEID,t2.UpdateCounter
FROM
   tbl_Partner t1
      inner join
   tbl_Partner t2
      on
          t1.RISEID = t2.RISEID
      left join
   tbl_Partner t1_anti
      on
          t1.RISEID = t1_anti.RISEID and
          t1_anti.UpdateCounter < t1.UpdateCounter
      left join
   tbl_Partner t2_anti
      on
          t1.RISEID = t2_anti.RISEID and
          t2_anti.UpdateCounter > t2.UpdateCounter
where
    t1_anti.RISEID is null and
    t2_anti.RISEID is null

It's not clear if you want rows to appear for items where only a single row has a particular RISEID. If not, add an extra condition into the join between t1 and t2, such that the UpdateCounter is higher on t2.

The two outer joins are to ensure that there is no earlier row than t1 (t1_anti) and no later row than t2 (t2_anti). In the WHERE clause, we ensure that those joins were unsuccessful.


Alternate one, using slightly more modern style:

;With OrderedRows as (
    Select RecordID,RISEID,UpdateCounter,
      ROW_NUMBER() OVER (PARTITION BY RISEID ORDER BY UpdateCounter ASC) as rnEarly,
      ROW_NUMBER() OVER (PARTITION BY RISEID ORDER BY UpdateCounter DESC) as rnLate
    from tbl_Partner
)
SELECT t1.RecordID,t1.RISEID,t2.UpdateCounter
FROM
   OrderedRows t1
       inner join
   OrderedRows t2
       on
            t1.RISEID = t2.RISEID
WHERE
    t1.rnEarly = 1 and
    t2.rnLate = 1

which may require fewer scans on the table.


Select Max UpdateCounter

 select distinct(
 (select top 1 recordid from tbl_partner p2 where p2.riseid=p1.riseid p2.updatecounter ASC
 ) )as RecordID,(select  Max(updatecounter) from tbl_partner p2 where p2.riseid=p1.riseid   ) as MaxUpdateCounter , riseid  from tbl_partner p1
0

精彩评论

暂无评论...
验证码 换一张
取 消