#sql #amazon-redshift
#sql #amazon-redshift
Вопрос:
У меня есть два сообщения (‘usb_port_reset’,’onewire_cable’) в столбце lbb_diag_value в одной таблице.
Я использую два столбца: created_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
Текущее решение: я использую функцию задержки и соединение по левому краю, и это работает нормально, если у меня нет последовательных сообщений 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:
Будет ли работать вложить вложенный выбор с задержками и отфильтровать записи, в которых нет изменений в 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'