Как поворачивать таблицу без многократного объединения - PullRequest
0 голосов
/ 12 декабря 2018

У меня есть таблица ctrlr_err_hist, в которой есть следующие столбцы:

visit_id
err_cd
err_name
m1_err_cnt
m2_err_cnt

Возможные значения для err_cd: 0, 1, 3.

Теперь я хочу написатьзапрос с разными ошибками с одинаковым visit_id в одной строке.Например, если в таблице есть следующие записи:

visit_id    err_cd    err_name    m1_err_cnt
    1         0       encoder        500
    1         3       breakout       212
    2         1       obclose         45
    2         3       breakout       143

Эта таблица будет объединена с таблицей tchn_visit_hist в visit_id.Если нет данных для какого-либо из err_cd, он будет нулевым.Конечный результат будет выглядеть следующим образом:

visit_id    encoder_cnt     breakout_cnt   obclose_cnt
    1         500              212           null
    2         null             143            45

Я написал следующий запрос, который трижды объединяет одну и ту же таблицу

select t.visit_id, t.door_id, enc.encoder_cnt, brk.breakout_cnt, ob.ob_close_cnt
from tchn_visit_hist t
left join (
    select m1_err_cnt as encoder_cnt, visit_id
    from ctrlr_err_hist  
    where err_cd = '0' 
) as enc 
on t.visit_id = enc.visit_id
left join (
    select m1_err_cnt as breakout_cnt, visit_id
    from ctrlr_err_hist  
    where err_cd = '3'
) as brk 
on t.visit_id = brk.visit_id
left join (
    select m1_err_cnt as ob_close_cnt, visit_id
    from ctrlr_err_hist  
    where err_cd = '1'
) as ob 
on t.visit_id = ob.visit_id

Интересно, есть ли лучший, более эффективный способ выполненияэто.

Ответы [ 2 ]

0 голосов
/ 12 декабря 2018

demo: db <> fiddle

Простой поворот можно получить следующим образом:

SELECT
    visit_id,
    MIN(m1_err_cnt) FILTER (WHERE err_cd = 0) as encoder_cnt,
    MIN(m1_err_cnt) FILTER (WHERE err_cd = 1) as ob_close_cnt,
    MIN(m1_err_cnt) FILTER (WHERE err_cd = 3) as breakout_cnt
FROM
    ctrlr_err_hist
GROUP BY visit_id

Группировка по visit_id и агрегирование столбцовзаинтересованы в. Предложение FILTER фильтрует элемент, который должен быть агрегирован.В этом случае агрегация только для одного специального err_cd.

Обратите внимание, что вы должны использовать функцию агрегирования.Это потому, что теоретически вы можете иметь две или более строки с (visit_id = 1, err_cd = 0).В этом случае вы должны решить, что вы хотите сделать с несколькими значениями (SUM, MIN, MAX, AVG, что угодно).Поскольку ваш пример содержит отдельные строки, это не имеет значения.

После этого вы просто объединяетесь со своей таблицей tchn_visit_hist:

SELECT t.visit_id, t.door_id, c.encoder_cnt, c.breakout_cnt, c.ob_close_cnt
FROM (
   SELECT
       visit_id,
       MIN(m1_err_cnt) FILTER (WHERE err_cd = 0) as encoder_cnt,
       MIN(m1_err_cnt) FILTER (WHERE err_cd = 1) as ob_close_cnt,
       MIN(m1_err_cnt) FILTER (WHERE err_cd = 3) as breakout_cnt
   FROM
       ctrlr_err_hist
   GROUP BY visit_id
) c
JOIN tchn_visit_hist t
ON (t.visit_id = c.visit_id)
0 голосов
/ 12 декабря 2018

Вы можете сделать Условие в Join

select 
  a.visit_id, 
  max(b.encoder_cnt) as encoder_cnt, 
  max(b.breakout_cnt) as breakout_cnt, 
  max(b.ob_close_cnt) as ob_close_cnt
from 
  tchn_visit_hist a
  left join(select 
              case when err_cd = '0' then m1_err_cnt end as encoder_cnt, 
              case when err_cd = '3' then m1_err_cnt end as breakout_cnt,
              case when err_cd = '1' then m1_err_cnt end as ob_close_cnt,
              case when err_cd = '0' then visit_id end as encoder_visit, 
              case when err_cd = '3' then visit_id end as breakout_visit,
              case when err_cd = '1' then visit_id end as ob_close_visit
            from
              tchn_visit_hist) b on case 
                                      when a.err_cd = '0' then a.visit_id = encoder_visit
                                      when a.err_cd = '3' then a.visit_id = breakout_visit
                                      when a.err_cd = '1' then a.visit_id = ob_close_visit
                                     end
group by
   a.visit_id
order by
   a.visit_id asc

Здесь Демо

...