Первое ненулевое значение на группу в таблице со многими столбцами - PullRequest
2 голосов
/ 19 апреля 2020

Проблема нахождения первых ненулевых значений широко обсуждается на SO, но все решения проблематичны c по некоторым причинам, возможно, из-за моей неопытности с PostgreSQL. У меня есть следующая структура в таблице:

group           submitted   num1  num2  num3  str1  str2  str3 ...
   32  14:04:21 4.5.2020.      2     1  Null  Null  Null  Null
   32  13:01:23 4.5.2020.   Null     1     0   abc   def  Null
   37  15:01:44 3.2.2020.      2  Null     0  Null  Null   aar
   37  03:04:21 2.1.2020.   Null     1     0   abc   def  Null
   37  23:04:00 1.1.2020.      2  Null     0   trt   def   abg
   ...

Желаемый результат приведенного выше примера:

group  num1  num2  num3  str1  str2  str3 ...
   32     2     1     0   abc   def  Null
   37     2     1     0   abc   def   aar
...

Имеется более 40 столбцов, и производительность важна. Мне нужна одна строка на группу, содержащая последнее ненулевое значение во времени или первое ненулевое значение в указанном выше (отсортированном) наборе данных. До сих пор я пробовал:

1) Сортировать по представленным групповым группам, и затем я не смог найти функцию агрегирования, которая находит первый ненулевой. Можно ли каким-то образом создать пользовательскую функцию агрегирования?

2) Использование решений с оконными функциями:

...
first_value(education) OVER (PARTITION BY CASE ORDER BY submitted WHEN education IS NOT NULL THEN submitted END) as education,
...

очень медленные (в сотни раз медленнее, чем групповые с MAX) ) и я чувствую, так как все таблицы имеют один и тот же раздел, что это не должно повторяться для каждого столбца. Есть ли способ выполнить разбиение по всей таблице, а затем искать первое значение для столбца?

3) В некоторых решениях упоминается ROWNUM. Проблема с этим (и большинством решений) заключается в том, что после первой сортировки и разбиения нет необходимости go проходить через все значения в столбце.

Тип решения, на который я надеюсь, - это аналог pandas первый .

1 Ответ

3 голосов
/ 19 апреля 2020

Есть хитрость, которая заключается в использовании array_agg() и удалении нулей. Это будет:

select groupid,
       (array_remove(array_agg(num1 order by submitted desc), null))[1] as num1,
       (array_remove(array_agg(num2 order by submitted desc), null))[1] as num2,
       . . .
from t
group by groupid;

Здесь - это дб <> скрипка.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...