2016-10-25 3 views
0

У меня есть таблица со структурой вроде этого, которая представляет изменения статуса.распространять иерархические значения из одного столбца

+-----------+----------+----------------+-----------------+-------+ 
| record_id | group_id | attribute type | change date | value | 
+-----------+----------+----------------+-----------------+-------+ 
|   1 |  1 | status   | 4/16/2008 18:59 | s1 | 
|   2 |  1 | details  | 4/16/2008 18:59 | d5 | 
|   3 |  1 | details  | 8/7/2008 18:31 | d2 | 
|   4 |  1 | details  | 2/5/2009 22:15 | d1 | 
|   5 |  1 | status   | 4/3/2009 21:27 | s2 | 
|   6 |  1 | details  | 4/3/2009 21:27 | d7 | 
|   7 |  2 | status   | 4/3/2009 21:46 | s1 | 
|   8 |  2 | details  | 4/3/2009 21:46 | d1 | 
+-----------+----------+----------------+-----------------+-------+ 

Я хотел бы запросить изменения статуса и сведения о состоянии изменения в двух столбцах, сгруппированные по временной метке (фактически любое изменение состояния делает изменения в детали, поэтому только детали изменить метки время может быть использованы для облегчения группировки) и статус распространяется на соответствующие детали, например:

+-----------+-----------------+--------+---------+ 
| object id | change date | status | details | 
+-----------+-----------------+--------+---------+ 
|   1 | 4/16/2008 18:59 | s1  | d5  | 
|   1 | 8/7/2008 18:31 | s1  | d2  | 
|   1 | 2/5/2009 22:15 | s1  | d1  | 
|   1 | 4/3/2009 21:27 | s2  | d3  | 
|   2 | 4/3/2009 21:46 | s1  | d1  | 
+-----------+-----------------+--------+---------+ 

это то, что я начал с, но она оставляет меня нулями

 SELECT history.record_id, 
       history.group_id, 
       history.changedate, 
       status_chages.value AS status, 
       history.value AS details 
     FROM history 
     LEFT JOIN (SELECT 
      history.group_id, 
      history.changedate, 
      history.value 
      FROM history 
      WHERE history.attribute_type = 'status') status_chages 
     ON status_chages.group_id = history.group_id AND 
      status_chages.changedate = history.changedate 
     WHERE history.attribute = 'details' 

Первая вещь, которая пришла т o мой ум должен заполнить NULL с данными предыдущих строк.

Но есть ли лучший способ для запроса результата, указанного выше?

+0

Какие СУБД вы используете? –

+0

На данный момент я пытаюсь сделать это с помощью Postgres, но целевая СУБД, вероятно, будет MS SQL Sever (добавленные теги). – Andrey

+0

Зачем разрабатывать Postgres при планировании использования SQL Server в процессе производства? Эти две СУБД действительно очень разные –

ответ

2

Запрос дает нужный макет:

select 
    group_id, 
    change_date, 
    max(case attr_type when 'status' then value else null end) as status, 
    max(case attr_type when 'status' then null else value end) as detail 
from history 
group by 1, 2 
order by 1, 2; 

group_id |  change_date  | status | detail 
----------+---------------------+--------+-------- 
     1 | 2008-04-16 18:59:00 | s1  | d5 
     1 | 2008-08-07 18:31:00 |  | d2 
     1 | 2009-02-05 22:15:00 |  | d1 
     1 | 2009-04-03 21:27:00 | s2  | d7 
     2 | 2009-04-03 21:46:00 | s1  | d1 
(5 rows) 

Вы можете заполнить пустые значения с предыдущими значениями таким образом:

select 
    group_id, 
    change_date, 
    max(status) over (partition by group_id, part) status, 
    detail 
from (
    select *, count(status) over (partition by group_id order by change_date) part 
    from (
     select 
      group_id, 
      change_date, 
      max(case attr_type when 'status' then value else null end) as status, 
      max(case attr_type when 'status' then null else value end) as detail 
     from history 
     group by 1, 2 
     ) s 
    ) s 
order by 1, 2; 

group_id |  change_date  | status | detail 
----------+---------------------+--------+-------- 
     1 | 2008-04-16 18:59:00 | s1  | d5 
     1 | 2008-08-07 18:31:00 | s1  | d2 
     1 | 2009-02-05 22:15:00 | s1  | d1 
     1 | 2009-04-03 21:27:00 | s2  | d7 
     2 | 2009-04-03 21:46:00 | s1  | d1 
(5 rows)  

Test it in rextester.

+0

Работает для меня, спасибо! И работает лучше (по крайней мере в моей среде), чем запрос на основе JOIN в качестве первого шага. – Andrey

Смежные вопросы