2017-11-07 3 views
1

ich wirklich etwas Hilfe hier vor meinem Kopf explodiert verwenden könnte ... Da die folgende Datenstruktur:Postgres Bauen Complex JSON-Objekt von Wide Spalte wie Design Schlüssel Wert

SELECT * FROM (VALUES (1, 1, 1, 1), (2, 2, 2, 2)) AS t(day, apple, banana, orange); 

day | apple | banana | orange 
-----+-------+--------+-------- 
    1 |  1 |  1 |  1 
    2 |  2 |  2 |  2 

Ich möchte ein JSON konstruieren Objekt, das wie folgt aussieht:

{ 
    "data": [ 
    { 
     "day": 1, 
     "fruits": [ 
     { 
      "key": "apple", 
      "value": 1 
     }, 
     { 
      "key": "banana", 
      "value": 1 
     }, 
     { 
      "key": "orange", 
      "value": 1 
     } 
     ] 
    } 
    ] 
} 

Vielleicht bin ich nicht so weit weg von meinem Ziel:

SELECT json_build_object(
    'data', json_agg(
    json_build_object(
     'day', t.day, 
     'fruits', t) 
    ) 
) FROM (VALUES (1, 1, 1, 1), (2, 2, 2, 2)) AS t(day, apple, banana, orange); 

Ergebnisse in:

{ 
    "data": [ 
    { 
     "day": 1, 
     "fruits": { 
     "day": 1, 
     "apple": 1, 
     "banana": 1, 
     "orange": 1 
     } 
    } 
    ] 
} 

Ich weiß, dass es json_each ist, die den Trick tun kann. Aber ich habe Mühe, es auf die Abfrage anzuwenden.


bearbeiten: Dies ist meine aktualisierte Abfrage, die, glaube ich, ist ziemlich nahe. Ich habe den Gedanken fallen gelassen, es mit json_each zu lösen. Jetzt habe ich nur ein Array von fruits statt Anhängen an das fruits Objekt zurückgeben:

SELECT json_build_object(
    'data', json_agg(
     json_build_object(
      'day', t.day, 
      'fruits', json_build_object(
       'key', 'apple', 
       'value', t.apple, 
       'key', 'banana', 
       'value', t.banana, 
       'key', 'orange', 
       'value', t.orange 
      ) 
     ) 
    ) 
) FROM (VALUES (1, 1, 1, 1), (2, 2, 2, 2)) AS t(day, apple, banana, orange); 

Würde ich brauche eine Unterabfrage hinzufügen, um eine verschachtelte Aggregatfunktion zu verhindern?

Antwort

3

die Funktion verwenden jsonb_each() Paare zu bekommen (key, value), so müssen Sie die Anzahl der Spalten und ihre Namen nicht wissen, eine richtige Ausgabe zu erhalten:

select jsonb_build_object('data', jsonb_agg(to_jsonb(s) order by day)) 
from (
    select day, jsonb_agg(jsonb_build_object('key', key, 'value', value)) as fruits 
    from (
     values (1, 1, 1, 1), (2, 2, 2, 2) 
    ) as t(day, apple, banana, orange), 
    jsonb_each(to_jsonb(t)- 'day') 
    group by 1 
    ) s; 

Die obige Abfrage dieses Objekt gibt:

{ 
    "data": [ 
     { 
      "day": 1, 
      "fruits": [ 
       { 
        "key": "apple", 
        "value": 1 
       }, 
       { 
        "key": "banana", 
        "value": 1 
       }, 
       { 
        "key": "orange", 
        "value": 1 
       } 
      ] 
     }, 
     { 
      "day": 2, 
      "fruits": [ 
       { 
        "key": "apple", 
        "value": 2 
       }, 
       { 
        "key": "banana", 
        "value": 2 
       }, 
       { 
        "key": "orange", 
        "value": 2 
       } 
      ] 
     } 
    ] 
} 
+0

Danke für Ihre Hilfe. Das ist tolle Arbeit. Können Sie den Grund für das Minus nach 'to_jsonb (t)' erklären? –

+2

Er entfernt Schlüssel "Tag" von Jsonb zurückgegeben von to_jsonb (t), da Sie nur Apfel, Banane und Orange Schlüssel benötigen. –

Verwandte Themen