2016-10-25 4 views
0

Ich habe eine Tabelle mit einer Struktur wie dieser, die Statusänderungen darstellt.propagieren hierarchische Werte aus einer einzigen Spalte

+-----------+----------+----------------+-----------------+-------+ 
| 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 | 
+-----------+----------+----------------+-----------------+-------+ 

Ich möchte Statusänderungen und Statusdetails Änderungen in zwei Spalten abfragen, durch Zeitstempel gruppiert (eigentlich jeder Statusänderung Details macht ändern, so dass nur Details Zeitstempel ändern für eine einfachere Gruppierung verwendet werden könnte) und Status zu verwandten Details propagiert, wie folgt aus:

+-----------+-----------------+--------+---------+ 
| 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  | 
+-----------+-----------------+--------+---------+ 

das ist, was ich angefangen habe mit, aber es lässt mich mit NULLs

 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' 

das erste, was die t kam o meine Meinung ist, NULL mit vorherigen Zeilendaten zu füllen.

Aber gibt es einen besseren Ansatz für die Abfrage des oben aufgeführten Ergebnisses?

+0

Welche DBMS verwenden Sie? –

+0

Momentan versuche ich das mit Postgres, aber das Ziel-DBMS wäre wahrscheinlich MS SQL Server (Tags hinzugefügt) – Andrey

+0

Warum mit Postgres entwickeln, wenn Sie SQL Server in der Produktion verwenden möchten? Diese beiden DBMS sind wirklich sehr unterschiedlich –

Antwort

2

Die Abfrage gibt gewünschte Layout:

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) 

Sie nulls mit früheren Werten in einer solchen Art und Weise füllen:

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

Funktioniert für mich, danke! Und es funktioniert besser (zumindest in meiner Umgebung) als JOIN-basierte Abfrage als ein erster Schritt. – Andrey

Verwandte Themen