2017-08-16 4 views
1

Ce que j'ai:Obtenir la liste de définition de la colonne de requête

Deux tables Postgres, une avec les données, l'un des groupes d'agrégats. Les deux tables peuvent être des modifications, par ex. son plan pour ajouter des emplacements plus tard et également définir de nouvelles catégories.

locations: 
| id | zipcode | name | type | 
|----+---------+---------+--------| 
| 1 | 1234 | Burger1 | burger | 
| 2 | 1234 | Burger2 | burger | 
| 3 | 1234 | Gas1 | gas | 
| 4 | 5678 | FriesA | fries | 
| 5 | 9876 | FriesB | fries | 
| 6 | 9876 | GarageA | garage | 

categories: 
| category | item | 
|----------+--------| 
| food  | burger | 
| food  | fries | 
| car  | gas | 
| car  | garage | 

Ce que je vous attendre à obtenir: Le nombre d'installations par zip code, agrégées par catégories données:

result: 
| zipcode | cnt(food) | cnt(car) | 
|---------+-----------+----------| 
| 1234 |   2 |  1 | 
| 5678 |   1 |   | 
| 9876 |   1 |  1 | 

Ce que j'ai essayé: Faites pivoter la table à l'aide postgres' crosstab() - Fonction: (voir https://www.postgresql.org/docs/current/static/tablefunc.html#AEN186219).

Malheureusement, crosstab() returntype est un enregistrement, vous devez donc définir des définitions de colonnes explicites. Pour permettre les catégories à ajouter plus tard, je suis en train d'obtenir la liste des définitions de colonnes d'une requête:

SELECT * FROM crosstab(
    'SELECT location.zipcode, categories.category, count(location.id) 
    FROM locations 
    JOIN categories 
    ON categories.item = location.type 
    GROUP BY zipcode, categories.category' 
    , 
    'SELECT DISTINCT category FROM categories ORDER BY category ASC;') 
AS 
    ct(
     SELECT array_to_string(
      array_cat(
       array(SELECT 'zipcode varchar'::varchar), 
       array(SELECT DISTINCT (category || ' int')::varchar AS category FROM categories ORDER BY category ASC) 
      ), 
     ', ' 
     ) 
    ); 

Quel est le problème

Postgres n'acceptera une requête liste de définition de la colonne. Si possible, je veux éviter d'utiliser PL \ pgSQL-fonctions mais seulement querys "réguliers":

ERROR: syntax error at or near »select« 
LINE 16: select array_to_string(
     ^
+0

La façon facile de le faire est dynamique par outputing JSON. Est-ce que c'est bon pour toi? –

+0

À la fin j'ai besoin de la sortie désirée décrite à "résultat:" comme table de résultat de SQL. Mais puisque le temps de calcul n'a pas d'importance et que je ne vais pas traiter une énorme quantité de données, il serait bon de chaîner certaines conversions. – pete

Répondre

0
select zipcode, jsonb_object_agg(category, total) 
from (
     select zipcode, category, count(*) as total 
     from 
      locations l 
      inner join 
      categories c on l.type = c.item 
     group by zipcode, category 
    ) a 
    right join (
     (select distinct category from categories) c 
     cross join 
     (select distinct zipcode from locations) l 
    ) dc using (zipcode, category) 
group by zipcode 
; 
zipcode |  jsonb_object_agg  
---------+-------------------------- 
    9876 | {"car": 1, "food": 1} 
    5678 | {"car": null, "food": 1} 
    1234 | {"car": 1, "food": 2}