Функция LAG с функцией Case / Rank - PullRequest
0 голосов
/ 16 апреля 2019

У меня есть два сообщения ('usb_port_reset', 'onewire_cable') в столбце lbb_diag_value в одной таблице.

Я использую два столбца: create_at (с отметкой времени), lbb_diag_value

Проблема: я хочу связать one_wire_cable для всех последовательных сообщений usb_port_reset, пока в таблице не будет найден другой one_wire_cable.

Например:

         Created_at    lbb_diag_value
         1 PM          onewire_cable
         1:15 PM       usb_port_reset
         3:00 Pm       usb_port_reset
         12Pm          onewire_cable
         Some Time     usb_port_reset

Cuurent Решение: я использую функцию задержки и левое соединение, и это прекрасно работает, если у меня нет последовательных сообщений usb_port_reset.

Ниже мой код:

  WITH CTE
AS (
    SELECT e2.identifier
        ,e2.created_at
        ,e2.model
        ,e2.sw_pkg_version
        ,e2.type
        ,e2.lbb_diag_value
        ,e2.lbb_diag_type
    FROM (
        SELECT e1.identifier
            ,e1.created_at
            ,e1.model
            ,e1.sw_pkg_version
            ,e1.lbb_diag_type
            ,e1.lbb_diag_value
            ,e1.type
        FROM eld_messages e1
        WHERE e1.type = 'lbb_diag'
            AND e1.lbb_diag_type = 'usb_port_reset'
            AND { % condition created_filter % } e1.created_at { % endcondition % }
        ) e2
    )
    ,onewire
AS (
    SELECT e2.identifier
        ,e2.lbb_diag_value
        ,e2.created_at
        ,e2.type
        ,e2.lbb_diag_type
        ,e2.prev_lbb_diag_type
        ,e2.prev_created_at
        ,e2.prev_lbb_diag_value
        ,e2.model
        ,e2.sw_pkg_version
        ,e2.seqnum
    FROM (
        SELECT e1.identifier
            ,e1.created_at
            ,e1.lbb_diag_value
            ,e1.type
            ,e1.lbb_diag_type
            ,e1.event_id
            ,e1.model
            ,e1.sw_pkg_version
            ,LAG(e1.lbb_diag_type) OVER (
                PARTITION BY e1.identifier ORDER BY e1.created_at
                    ,e1.event_id DESC
                ) AS prev_lbb_diag_type
            ,LAG(e1.created_at) OVER (
                PARTITION BY e1.identifier ORDER BY e1.created_at
                    ,e1.event_id DESC
                ) AS prev_created_at
            ,LAG(e1.lbb_diag_value) OVER (
                PARTITION BY e1.identifier ORDER BY e1.created_at
                    ,e1.event_id
                ) AS prev_lbb_diag_value
            ,row_number() OVER (
                PARTITION BY e1.lbb_diag_type ORDER BY e1.created_at
                    ,e1.event_id DESC
                ) seqnum
        FROM eld_messages e1
        WHERE e1.type = 'lbb_diag'
            AND e1.lbb_diag_type IN (
                'onewire_cable'
                ,'usb_port_reset'
                )
            AND { % condition created_filter % } e1.created_at { % endcondition % }
        ORDER BY e1.identifier
            ,e1.created_at
        ) e2
    WHERE (
            e2.lbb_diag_type = 'usb_port_reset'
            AND e2.prev_lbb_diag_type = 'onewire_cable'
            )
        OR (
            CASE 
                WHEN e2.lbb_diag_type = 'usb_port_reset'
                    AND e2.prev_lbb_diag_type = 'usb_port_reset'
                    THEN e2.seqnum = 1
                END
            )
    )
SELECT cte.identifier
    ,cte.created_at
    ,cte.model
    ,cte.sw_pkg_version
    ,cte.type
    ,cte.lbb_diag_type
    ,cte.lbb_diag_value
    ,onewire.prev_lbb_diag_value AS onewire_lbb_diag_value
    ,onewire.prev_created_at AS onewire_created_at
FROM cte
LEFT JOIN onewire ON cte.identifier = onewire.identifier
    AND cte.created_at = onewire.created_at; 

1 Ответ

0 голосов
/ 18 апреля 2019

Будет ли работать вложенный выбор с задержками и отфильтровывать записи, где нет изменений в lbb_diag_value? Я не пытался понять весь контекст этого огромного запроса и, если вам нужны другие записи, но задержка может быть отличным способом определения границ, которые кажутся вам необходимыми.

FROM (
    SELECT * FROM (
        SELECT e1.identifier ,e1.created_at ,e1.lbb_diag_value ,e1.type ,e1.lbb_diag_type ,e1.event_id
            ,e1.model ,e1.sw_pkg_version
            ,LAG(e1.lbb_diag_type) OVER (PARTITION BY e1.identifier ORDER BY e1.created_at ,e1.event_id DESC) AS prev_lbb_diag_type
            ,LAG(e1.created_at) OVER ( PARTITION BY e1.identifier ORDER BY e1.created_at ,e1.event_id DESC) AS prev_created_at
            ,LAG(e1.lbb_diag_value) OVER ( PARTITION BY e1.identifier ORDER BY e1.created_at ,e1.event_id) AS prev_lbb_diag_value
            ,row_number() OVER (PARTITION BY e1.lbb_diag_type ORDER BY e1.created_at ,e1.event_id DESC) seqnum
        FROM eld_messages e1
        WHERE e1.type = 'lbb_diag' AND e1.lbb_diag_type IN ('onewire_cable' ,'usb_port_reset')
            AND { % condition created_filter % } e1.created_at { % endcondition % }
        ORDER BY e1.identifier, e1.created_at
    ) t
    WHERE lbb_diag_value != prev_lbb_diag_value
) e2

Если вам нужны все записи, вы можете сделать это в два суб-выбора с помощью объединения (выбор, который вы оставили, соединенный с выбором, который обнаруживает переходы), где переход (lbb_diag_value! = Prev_lbb_diag_value) заканчивается как новый столбец с указанием записей, которые переключаются с одного значения на другое.

Тогда определение 'onewire_cable' будет выглядеть примерно так:

select * from (
...join...
) j where j.flip = 1 and j.lbb_diag_value = 'onewire_cable'
...