SQL:ANSI Выводит таблицу с идентификаторами, когда значения сначала перемещаются от 0 до любого положительного числа

У меня есть таблица с идентификаторами, датами и значениями. Я хотел бы получить каждый уникальный идентификатор (дату и значение) в первый раз, когда значение перемещается конкретно с 0 на любое положительное число.

ID    DATE        Value   
1    2019-01-31     0
2    2019-02-27     0
3    2019-03-31     0

2    2019-01-31     5
1    2019-02-31     1
3    2019-04-31     5
2    2019-04-30     5
1    2019-05-31     10

3    2020-01-31     0
2    2020-02-28     3
1    2019-06-31     5
3    2020-04-30     5

Желаемый результат:

 ID    DATE        Value   
    1    2019-02-31     1
    2    2019-02-28     3
    3    2019-04-31     5

Я пытаюсь сделать это в снежинке, не уверен, что это на что-то повлияет.

некоторые из ваших дат недействительны, это должно быть исправлено.

Simeon Pilgrim 18.03.2022 01:16

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

pickledpasta22 18.03.2022 01:24
ReactJs | Supabase | Добавление данных в базу данных
ReactJs | Supabase | Добавление данных в базу данных
Это и есть ваш редактор таблиц в supabase.👇
Понимание Python и переход к SQL
Понимание Python и переход к SQL
Перед нами лабораторная работа по BloodOath:
0
2
24
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Для этого можно использовать КВАЛИФИКАЦИЯ и ROW_NUMBER():

Если вам нужно первое ненулевое значение... но вы просили об этом..

SELECT * 
FROM values
    (1, '2019-01-31'::date,0   ),
    (2, '2019-02-27'::date,0   ),
    (3, '2019-03-31'::date,0   ),
    (2, '2019-01-31'::date,5   ),
    (1, '2019-02-28'::date,1   ),
    (3, '2019-04-30'::date,5   ),
    (2, '2019-04-30'::date,5   ),
    (1, '2019-05-31'::date,10  ),
    (3, '2020-01-31'::date,0   ),
    (2, '2020-02-28'::date,3   ),
    (1, '2019-06-30'::date,5   ),
    (3, '2020-04-30'::date,5   )
    t(ID ,   DATE  ,      Value   )
QUALIFY value > 0 AND row_number() over(partition by id, value > 0 order by date ) = 1;
ORDER BY 1,2

Уловка, которую следует отметить, заключается в том, что вы хотите исключить все значения, не превышающие 0, и также разделить row_number на это.

дает:

Я БЫДАТАЦЕННОСТЬ
12019-02-281
22019-01-315
32019-04-305

возьми два:

Первый переход от 0 к ненулевому:

поэтому давайте просто упорядочим данные, чтобы мы говорили об одном и том же:

Я БЫДАТАЦЕННОСТЬв розыске
12019-01-310
12019-02-281это
12019-05-3110
12019-06-305
22019-01-315
22019-02-270
22019-04-305это
22020-02-283
32019-03-310
32019-04-305это
32020-01-310
32020-04-305

это можно сделать с помощью двух вложенных QUALIFY:

SELECT * FROM (
    SELECT *
    FROM values
        (1, '2019-01-31'::date,0   ),
        (2, '2019-02-27'::date,0   ),
        (3, '2019-03-31'::date,0   ),
        (2, '2019-01-31'::date,5   ),
        (1, '2019-02-28'::date,1   ),
        (3, '2019-04-30'::date,5   ),
        (2, '2019-04-30'::date,5   ),
        (1, '2019-05-31'::date,10  ),
        (3, '2020-01-31'::date,0   ),
        (2, '2020-02-28'::date,3   ),
        (1, '2019-06-30'::date,5   ),
        (3, '2020-04-30'::date,5   )
        t(ID ,   DATE  ,      Value   )
    QUALIFY lag(value)over(partition by id order by date) = 0
) 
QUALIFY row_number() over(partition by id order by date ) = 1
ORDER BY 1,2

дает:

Я БЫДАТАЦЕННОСТЬ
12019-02-281
22019-04-305
32019-04-305

ANSI-SQL:

Если вам нужен ANSI SQL, вы должны использовать эту форму:

SELECT 
    b.ID,
    b.DATE,
    b.Value
FROM (
    SELECT 
        a.ID,
        a.DATE,
        a.Value,
        row_number() over(partition by a.id order by a.date ) as rn
    FROM (
        SELECT 
            ID,
            DATE,
            Value,
            lag(value)over(partition by id order by date) as lag_val
        FROM table_data
    ) AS a
    WHERE a.lag_val = 0
) AS b
WHERE b.rn = 1
ORDER BY 1,2

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

Вау, это прекрасно работает. Впервые я вижу использование «Квалификации» и сейчас изучаю, как это работает. Большое спасибо!!

pickledpasta22 18.03.2022 01:18

Обратите внимание, что квалифицирование — это специальное ключевое слово Snowflake, а не часть ANSI SQL. В других СУБД вам потребуется либо использовать CTE, либо дополнительный подзапрос и предложение WHERE для достижения того же результата.

Paweł Sopel 18.03.2022 01:23

Приятно знать, спасибо за наводку.

pickledpasta22 18.03.2022 01:23

Snowflake, Databricks, Teradata и Oracle поддерживают Qualify.

Simeon Pilgrim 18.03.2022 03:14

Другие вопросы по теме