SQL: запрос на получение последнего изменения значения указанного c столбца - PullRequest
1 голос
/ 27 мая 2020

Итак, у меня есть таблица с информацией о продукте. Каждый раз при изменении указанного продукта c вставляется новая строка с новыми значениями, включая отметку времени и пользователя, который ее изменил.

Чтобы показать информацию, я ищу последнюю строку для указанного c продукта (который определяется столбцом, который является product_id).

Но теперь мне нужно знать, кто был последним человеком, который изменил один из указанных c столбцов с именем status.

Итак, допустим, моя таблица состоит из этого

По сути, мне нужно написать запрос, который скажет мне, когда было последнее изменение для этого столбца.

product_id | name | status   | user | keyid
--------------------------------------------
598        | prrr | 0        | john | 10
598        | prod | 1        | jane | 11
456        | abcd | 2        | mac  | 12
598        | prdd | 2        | kate | 13
598        | rdpd | 2        | jane | 14
456        | prrr | 3        | john | 15
456        | abbb | 3        | kate | 16

Итак, последняя информация для продукта 598:

598 rdpd 2 jane 14

НО последний человек, который изменил выпуск, - это kate

Последняя информация для продукта 456:

456 abbb 3 kate 16

НО последний человек, который изменил выпуск, - это john

Так что в идеале я бы хочу написать запрос, который вернет

598 kate 13
456 john 15

У меня даже нет идеи, как написать такой запрос, поэтому мне интересно, может ли кто-нибудь мне здесь помочь.

Ответы [ 2 ]

0 голосов
/ 01 июня 2020

Если ваша база данных не поддерживает оконные функции, logi c немного сложнее.

В качестве начала рассмотрим следующий запрос, который дает вам первые idkey строк, которые иметь последние status на product_id:

select product_id, min(keyid)
from mytable t
where not exists (
    select 1 
    from mytable t1 
    where t1.product_id = t.product_id and t1.status <> t.status and t1.keyid > t.keyid
)
group by product_id

Это возвращает:

product_id | min(keyid)
---------: | ---------:
       598 |         13
       456 |         15

Затем вы можете использовать этот набор результатов для фильтрации таблицы:

select t.*
from mytable t
where t.keyid in (
    select min(keyid)
    from mytable t
    where not exists (
        select 1 
        from mytable t1 
        where t1.product_id = t.product_id and t1.status <> t.status and t1.keyid > t.keyid
    )
    group by product_id
)

Результаты:

product_id | name | status | user | keyid
---------: | :--- | -----: | :--- | ----:
       598 | prdd |      2 | kate |    13
       456 | prrr |      3 | john |    15

Демо на DB Fiddle

0 голосов
/ 27 мая 2020

Вы можете использовать оконные функции:

select t.*
from (select t.*, row_number() over (partition by productid order by keyid desc) as seqnum
      from (select t.*,
                   lag(status) over (partition by productid order by keyid) as prev_status
            from t
           ) t
      where prev_status is null or prev_status <> status
     ) t
where seqnum = 1;

Самый внутренний подзапрос сравнивает каждое значение с его предыдущим значением. Средний подзапрос перечисляет каждую строку для продукта, статус которого изменился. Внешний запрос фильтрует, чтобы получить последний.

...