Обновить значение столбца в запросе SELECT

У меня сложный вопрос по SQL.

Можем ли мы обновить столбец в запросе SELECT? Пример:

Рассмотрим эту таблицу:

    |ID   |SeenAt  |
    ----------------
    |1    |20      |
    |1    |21      |
    |1    |22      |
    |2    |70      |
    |2    |80      |

Мне нужен запрос SELECT, который дает для каждого идентификатора, когда он был замечен в первый раз. И когда это видели «снова»:

    |ID   |Start  |End  |
    ---------------------
    |1    |20     |21   |
    |1    |20     |22   |
    |1    |20     |22   |
    |2    |70     |80   |
    |2    |70     |80   |

Во-первых, оба столбца Start и End будут иметь одинаковое значение, но когда появится вторая строка с тем же ID, нам нужно обновить ее предшественницу, чтобы присвоить End новое значение SeenAt. Мне удалось создать столбец Start, я даю минимальное значение SeenAt на ID всем идентификаторам. Но я не могу найти способ каждый раз обновлять столбец End.

Не обращайте внимания на двойники, у меня есть другие столбцы, которые меняются в каждой новой строке.

Кроме того, я работаю в Impala, но могу использовать Oracle.

Я надеюсь, что я был достаточно ясен. Спасибо


person Haha    schedule 30.07.2019    source источник
comment
Судя по всему, вам нужны аналитические функции min() и max(). Или, возможно, метод tabibitosan, если вы ищете последовательные группы идентификатора (например, что, если новая строка для идентификатора = 1 был добавлен с Seeat 30. Будет ли это отдельная группа или она будет принадлежать первой группе с min = 20 и max = 30?   -  person Boneist    schedule 30.07.2019
comment
Вы уверены в значениях в выводе для End? Я полагаю, что они должны быть 20,21,22,70,80, не так ли?   -  person Barbaros Özhan    schedule 30.07.2019
comment
Конец должен содержать начальное значение новой строки с тем же идентификатором.   -  person Haha    schedule 30.07.2019


Ответы (3)


Вы можете использовать lead() и nvl():

select id, min(seenat) over (partition by id) seen_start,
       nvl(lead(seenat) over (partition by id order by seenat), seenat) seen_end
  from t 

демонстрация

person Ponder Stibbons    schedule 30.07.2019

Старт прост, всего MIN из GROUP

В конце вам нужно найти MIN после SeenAt, а если вы его не найдете, то текущий SeenAt

ДЕМО-версия SQL

SELECT "ID", 
        (SELECT MIN("SeenAt")
         FROM Table1 t2
         WHERE t1."ID" = t2."ID") as "Start",
        COALESCE(
                 (SELECT MIN("SeenAt")
                  FROM Table1 t2
                  WHERE t1."ID" = t2."ID"
                  AND t1."SeenAt" < t2."SeenAt")
                 , t1."SeenAt"
                ) as End

FROM Table1 t1

ВЫВОД

| ID | START | END |
|----|-------|-----|
|  1 |    20 |  21 |
|  1 |    20 |  22 |
|  1 |    20 |  22 |
|  2 |    70 |  80 |
|  2 |    70 |  80 |
person Juan Carlos Oropeza    schedule 30.07.2019

вам, кажется, нужна min() аналитическая функция с self-join:

select distinct t1.ID,
       min(t1.SeenAt) over (partition by t1.ID order by t1.ID) as "Start",
       t2.SeenAt as "End"
  from tab t1
  join tab t2 on t1.ID=t2.ID and t1.SeenAt<=t2.SeenAt
 order by t2.SeenAt;

Демо

person Barbaros Özhan    schedule 30.07.2019