Поиск обновлений в таблице с помощью самостоятельного соединения

У меня есть таблица, как показано ниже

tablename - свойство

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

Как вы можете видеть в приведенном выше коде, есть runId и идентификатор листинга. Я пытаюсь получить конкретный runId, который представляет собой добавленные новые листинги (в данном случае для runId 2 его 4-я строка с идентификатором листинга 567) и которые являются обновленными идентификаторами листинга (в этом случае его строка 3 и строка 5 с listId 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 - это язык ... какая у вас СУБД sqlserver, _2 _... и т. д., также укажите свою версию СУБД.   -  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