简体   繁体   中英

Finding updates in a table using Self-Join

I have a table as shown below

tablename - property

|runId|listingId|listingName
   1    123       abc
   1    234       def
   2    123       abcd
   2    567       ghi
   2    234       defg

As you can see in above code there is a runId and there is a listing Id. I am trying to fetch for a particular runId which are the new listings added (In this case for runId 2 its 4th row with listing id 567 ) and which are the listing Ids that are update (In this case its row 3 and row 5 with listingId 123 and 234 respectively)

I am trying self join and it is working fairly for new updates but new additions are giving me trouble

SELECT p1.* FROM property p1 
    INNER JOIN  property p2 
        ON p1.listingid = p2.listingid 
            WHERE p1.runid=456 AND p2.runid!=456

The above query provides me correct updated records in the table. But I am not able to find new listing. I used p1.listingid != p2.listingId , left outer join, still wont work.

You may try this.

with cte as (
select row_number() over (partition by listingId order by runId) as Slno, * from property 
)
select * from property where listingId not in (
select  listingId from cte as c where slno>1 
)    --- for new listing added

with cte as (
select row_number() over (partition by listingId order by runId) as Slno, * from property 
)
select * from property where listingId in (
select  listingId from cte as c where slno>1 
)   --- for modified listing 


I would use the ROW_NUMBER() analytical function for it.

SELECT
    T.*
FROM
    (
        SELECT
            T.*,
            CASE
                WHEN ROW_NUMBER() OVER(
                    PARTITION BY LISTINGID
                    ORDER BY
                        RUNID
                ) = 1 THEN 'INSERTED'
                ELSE 'UPDATED'
            END AS OPERATION_
        FROM
            PROPERTY
    )
WHERE
    RUNID = 2
    -- AND OPERATION_ = 'INSERTED'
    -- AND OPERATION_ = 'UPDATED'

This will provide the result as updated if listingid is added in any of the previous runid

Cheers!!

For this, I would recommend exists and not exists . For updates:

select p.*
from property p
where exists (select 1
              from property p2
              where p2.listingid = p.listingid and
                    p2.runid < p.runid
             );

If you want the result for a particular runid , add and runid = ? to the outer query.

And for new listings:

select p.*
from property p
where not exists (select 1
                  from property p2
                  where p2.listingid = p.listingid and
                        p2.runid < p.runid
                 );

With an index on property(listingid, runid) , I would expect this to have somewhat better performance than a solution using window functions.

Here is a db<>fiddle.

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