Menemukan pembaruan dalam tabel menggunakan Self-Join

Saya memiliki tabel seperti yang ditunjukkan di bawah ini

nama tabel - properti

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

Seperti yang Anda lihat pada kode di atas, ada runId dan ada Id listing. Saya mencoba mengambil runId tertentu yang merupakan daftar baru yang ditambahkan (Dalam hal ini untuk runId 2 baris ke-4 dengan id daftar 567 ) dan yang merupakan Id daftar yang diperbarui (Dalam hal ini baris 3 dan baris 5 dengan listingId 123 dan 234 masing-masing)

Saya mencoba bergabung sendiri dan berfungsi dengan baik untuk pembaruan baru tetapi penambahan baru membuat saya kesulitan

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

Kueri di atas memberi saya catatan terbaru yang benar dalam tabel. Tapi saya tidak dapat menemukan daftar baru. Saya menggunakan p1.listingid != p2.listingId , gabung luar kiri, masih tidak berfungsi.


person Sandeep Nair    schedule 05.09.2019    source sumber
comment
sql adalah bahasa...apa DBMS Anda sqlserver, mysql...dll, sebutkan juga versi DBMS Anda.   -  person DarkRob    schedule 05.09.2019


Jawaban (3)


Saya akan menggunakan fungsi analitik ROW_NUMBER() untuk itu.

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'

Ini akan memberikan hasil yang diperbarui jika listingid ditambahkan di runid sebelumnya

Bersulang!!

person Popeye    schedule 05.09.2019

Anda dapat mencoba ini.

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 


person DarkRob    schedule 05.09.2019

Untuk ini, saya akan merekomendasikan exists dan not exists. Untuk pembaruan:

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

Jika Anda menginginkan hasil untuk runid tertentu, tambahkan and runid = ? ke kueri luar.

Dan untuk listingan baru:

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

Dengan indeks pada property(listingid, runid), saya berharap ini memiliki kinerja yang lebih baik daripada solusi yang menggunakan fungsi jendela.

Ini adalah db‹>biola.

person Gordon Linoff    schedule 05.09.2019
comment
Ini terlihat paling mirip karena pembaruan berfungsi dengan baik jika saya mengubah p2.runid ‹ p.runid dengan p2.runid != 2 dan p.runid=2 . Namun hal yang sama tidak berlaku untuk listingan baru. - person Sandeep Nair; 05.09.2019
comment
@SandeepNair . . . Logikanya berfungsi dengan baik. Jika Anda menginginkan hasil untuk runid tertentu, tambahkan saja runid tersebut ke klausa where terluar. - person Gordon Linoff; 05.09.2019