Исходная метка столбца LEAST / GREATEST - PullRequest
0 голосов
/ 28 мая 2018

Я создал столбец, который показывает самую раннюю временную метку, и теперь я хочу создать другой столбец, который показывает источник этой временной метки.Это то, что я использую, но оно не работает, когда одно из значений временной метки в необработанных данных равно NULL.

SELECT LEAST (timestamp_1, timestamp_2, timestamp_3)
       ,CASE WHEN timestamp_1 is null AND timestamp_2 is null AND timestamp_3 is null THEN NULL
        ELSE CASE WHEN timestamp_1 <= timestamp_2 AND timestamp_1 <= timestamp_3 THEN 'timestamp_1'
                  WHEN timestamp_2 <= timestamp_3 THEN 'timestamp_2'
                  ELSE 'timestamp_3' END
       END timestamp_source

FROM (

    SELECT timestamp_1
           ,timestamp_2
           ,timestamp_3
           ,timestamp_4
    FROM time
)

Я хочу, чтобы результат выглядел следующим образом:

timestamp_1 | timestamp_2 | timestamp_3 | timestamp_4 | MIN_time    | MIN_source

8/5/18 7:00 | 8/5/18 5:00 | NULL        | 8/5/18 9:00 | 8/5/18 5:00 | timestamp_2
9/5/18 9:00 | 8/5/18 7:00 | 8/5/18 3:00 | NULL        | 8/5/18 3:00 | timestamp_3

Есть ли более прямой способ достижения результата?

1 Ответ

0 голосов
/ 28 мая 2018

Это просто больно.Один метод, который хорошо обобщает, использует агрегацию.Производительность не такая хорошая, как при использовании CASE, и предполагается, что строки имеют уникальный идентификатор:

SELECT DISTINCT id, MIN(ts) OVER (PARTITION BY id) as min_ts,
       FIRST_VALUE(which) OVER (PARTITION BY id ORDER BY ts)
FROM ((SELECT id, 'timestamp_1' as which, timestamp_1 as ts
       FROM time
      ) UNION ALL
      (SELECT id, 'timestamp_2' as which, timestamp_2 as ts
       FROM time
      ) UNION ALL
      (SELECT id, 'timestamp_3' as which, timestamp_3 as ts
       FROM time
      ) UNION ALL
      (SELECT id, 'timestamp_4' as which, timestamp_4 as ts
       FROM time
      ) 
     ) t;

Я не фанат select distinct, но Redshift не поддерживает first_value(), так какфункция агрегирования.

Альтернативой является использование некоторого будущего значения, чтобы избежать NULL:

select nullif(least(timestamp_1, timestamp_2, timestamp_3, timestamp_4), '9999-01-01') as least_ts,
       (case when timestamp_1 = least(timestamp_1, timestamp_2, timestamp_3, timestamp_4) then 'timestamp_1'
             when timestamp_2 = least(timestamp_1, timestamp_2, timestamp_3, timestamp_4) then 'timestamp_2'
             when timestamp_3 = least(timestamp_1, timestamp_2, timestamp_3, timestamp_4) then 'timestamp_3'
             else 'timestamp_4'
        end) as which
from (select coalesce(timestamp_1, '9999-01-01') as timestamp_1,
             coalesce(timestamp_2, '9999-01-01') as timestamp_2,
             coalesce(timestamp_3, '9999-01-01') as timestamp_3,
             coalesce(timestamp_4, '9999-01-01') as timestamp_4
      from time
     ) t;

Примечание. Я предполагаю, что вы используете Redshift.У Postgres есть более простые способы сделать это.

...