ค้นหาการอัพเดตในตารางโดยใช้ Self-Join

ฉันมีตารางดังภาพด้านล่าง

ชื่อตาราง - คุณสมบัติ

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

ดังที่คุณเห็นในโค้ดด้านบน มี runId และมี List Id ฉันกำลังพยายามดึงข้อมูลสำหรับ runId เฉพาะซึ่งเป็นรายการใหม่ที่เพิ่ม (ในกรณีนี้สำหรับ runId 2 แถวที่ 4 พร้อมรหัสรายการ 567 ) และรหัสรายการใดที่อัปเดต (ในกรณีนี้คือแถว 3 และแถว 5 ด้วย รายชื่อId 123 และ 234 ตามลำดับ)

ฉันกำลังลองเข้าร่วมด้วยตนเองและใช้งานได้ดีสำหรับการอัปเดตใหม่ แต่การเพิ่มใหม่ทำให้ฉันมีปัญหา

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

ข้อความค้นหาข้างต้นให้บันทึกที่อัปเดตที่ถูกต้องในตารางแก่ฉัน แต่ฉันไม่สามารถหารายการใหม่ได้ ฉันใช้ p1.listingid != p2.listingId การรวมภายนอกด้านซ้ายยังคงใช้งานไม่ได้


person Sandeep Nair    schedule 05.09.2019    source แหล่งที่มา
comment
sql คือภาษา...DBMS ของคุณคืออะไร sqlserver, mysql...ฯลฯ รวมถึงพูดถึงเวอร์ชันของ DBMS ของคุณด้วย   -  person DarkRob    schedule 05.09.2019


คำตอบ (3)


ฉันจะใช้ฟังก์ชันการวิเคราะห์ ROW_NUMBER() สำหรับมัน

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'

สิ่งนี้จะให้ผลลัพธ์ที่อัปเดตหากมีการเพิ่ม listingid ใน runid ก่อนหน้าใดๆ

ไชโย!!

person Popeye    schedule 05.09.2019

คุณอาจลองสิ่งนี้

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

สำหรับเรื่องนี้ ฉันขอแนะนำ exists และ not exists สำหรับการอัปเดต:

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

หากคุณต้องการผลลัพธ์สำหรับ runid เฉพาะ ให้เพิ่ม and runid = ? ลงในแบบสอบถามภายนอก

และสำหรับรายการใหม่:

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

ด้วยดัชนีบน property(listingid, runid) ฉันคาดหวังว่าสิ่งนี้จะมีประสิทธิภาพที่ดีกว่าโซลูชันที่ใช้ฟังก์ชันหน้าต่าง

นี่คือ นี่คือ db‹>ซอ

person Gordon Linoff    schedule 05.09.2019
comment
สิ่งนี้ดูใกล้เคียงที่สุดเนื่องจากการอัพเดตทำงานได้ดีหากฉันเปลี่ยน p2.runid ‹ p.runid ด้วย p2.runid != 2 และ p.runid=2 แต่สิ่งเดียวกันนั้นใช้ไม่ได้กับรายการใหม่ - person Sandeep Nair; 05.09.2019
comment
@SandeepNair . . . ตรรกะทำงานได้ดี หากคุณต้องการผลลัพธ์สำหรับ runid เฉพาะเจาะจง เพียงเพิ่ม runid นั้นเข้าไปในส่วนคำสั่ง where ภายนอก - person Gordon Linoff; 05.09.2019