Подсчитать самое последнее количество последовательных строк с нулевым значением - PullRequest
2 голосов
/ 12 февраля 2020

Я делаю некоторый анализ данных в PostgreSQL 10.6, основываясь на этой демонстрационной настройке:

create table history (
    registered_unix int,
    requested_unix int,
    alias character varying(255)
);

INSERT INTO history VALUES
  (1537841388, 1537878224, '3')
, (1538093202, 1538095740, '1')
, (1538093186, 1538095740, '3')
, (1538105501, 1538107039, '2')
, (1538105501, 1538107039, '4')
, (1538205007, 1538242243, '2')
, (1538205012, NULL      , '1')
, (1538105501, NULL      , '1')
, (1538205007, NULL      , '3')
, (1538105501, NULL      , '3')
, (1538040863, NULL      , '3')
, (1537985996, NULL      , '3')
, (1538205007, NULL      , '4')
, (1538093186, NULL      , '4')
, (1538205301, NULL      , '5')
, (1538105501, NULL      , '5')
, (1538093186, NULL      , '5');

Я пытаюсь подсчитать количество последовательных alias строк, где requested_unix null, но только для первого вхождения и где последовательные вхождения больше или равны 2.

Данные отсортированы по псевдониму, а затем зарегистрированы_ unix DES C:

enter image description here

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

enter image description here

Псевдоним 1: включен b / c его 2 самых последних значения «требуемый_ unix» равны нулю.

Псевдоним 2: пропущено. Запрошенный unix имеет значение в своей последней строке

Псевдоним 3: Включен b / c его 2 самых последних значения "требуемый_ unix" равны нулю. Старые отбрасываются.

Псевдоним 4: Пропущено. Имеет только 1 самое последнее значение «требуемый_ unix» со значением ноль. 2-й ряд имеет значение.

Псевдоним 5: Включен. 3 последних последовательных значения равны нулю.

Существуют все виды билетов с подсчетом последовательных вхождений или обнаружением первого вхождения, но, похоже, я хочу объединить два подхода.

1 Ответ

1 голос
/ 12 февраля 2020

Используя DISTINCT ON, нам нужен только один подзапрос:

SELECT alias
     , CASE WHEN requested_unix IS NULL THEN ct   ELSE rn - 1          END AS missed
     , CASE WHEN requested_unix IS NULL THEN NULL ELSE registered_unix END AS last_success
     , most_recent
FROM  (
   SELECT DISTINCT ON (alias)
          *
        , row_number()         OVER (PARTITION BY alias ORDER BY registered_unix DESC) AS rn
        , count(*)             OVER (PARTITION BY alias) AS ct
        , max(registered_unix) OVER (PARTITION BY alias) AS most_recent
   FROM   history h
   ORDER  BY alias, requested_unix IS NULL, registered_unix DESC
   ) latest_success
WHERE (requested_unix IS NULL OR rn > 2);

db <> fiddle здесь

В подзапросе получить одну строку для alias с помощью DISTINCT ON (alias). ORDER BY делает его тем, который нам нужен.

  • 1-й элемент ЗАКАЗА alias должен соответствовать DISTINCT ON.

  • 2-й элемент ORDER-BY requested_unix IS NULL сортирует ненулевые значения сверху. (FALSE сортирует до TRUE.) requested_unix IS NOT NULL DESC может быть более интуитивно понятным, но я предпочитаю короткий код.

  • 3-й элемент ORDER-BY registered_unix DESC выбирает последняя строка среди них.

Добавить номер строки (rn), количество строк (ct) и самую последнюю registered_unix (most_recent) на раздел с оконными функциями (обрабатывается до DISTINCT ON), и у вас есть вся необходимая информация на одном уровне запросов. Внешний SELECT предназначен только для сборки запрошенного формата результата.

Связанный:

...