2013-03-27 3 views
3

Disons que j'ai un simple tableau agg_test avec 3 colonnes - id, column_1 et column_2. Dataset, par exemple:Agréger par agrégat (ARRAY_AGG)?

id|column_1|column_2 
-------------------- 
1|  1|  1 
2|  1|  2 
3|  1|  3 
4|  1|  4 
5|  2|  1 
6|  3|  2 
7|  4|  3 
8|  4|  4 
9|  5|  3 
10|  5|  4 

Une requête comme celui-ci (avec auto join):

SELECT 
    a1.column_1, 
    a2.column_1, 
    ARRAY_AGG(DISTINCT a1.column_2 ORDER BY a1.column_2) 
FROM agg_test a1 
JOIN agg_test a2 ON a1.column_2 = a2.column_2 AND a1.column_1 <> a2.column_1 
WHERE a1.column_1 = 1 
GROUP BY a1.column_1, a2.column_1 

produira un résultat comme celui-ci:

column_1|column_1|array_agg 
--------------------------- 
     1|  2|  {1} 
     1|  3|  {2} 
     1|  4| {3,4} 
     1|  5| {3,4} 

Nous pouvons voir que pour les valeurs 4 et 5 de la table jointe nous avons le même résultat dans la dernière colonne. Donc, est-il possible de grouper les résultats par ce biais, par exemple:

column_1|column_1|array_agg 
--------------------------- 
     1|  {2}|  {1} 
     1|  {3}|  {2} 
     1| {4,5}| {3,4} 

Merci pour les réponses. Si quelque chose n'est pas clair ou peut être mieux présenté - dites-moi dans les commentaires et je vais essayer de rendre cette question aussi lisible que possible.

Répondre

4

Je ne suis pas sûr si vous pouvez agréger par un tableau. Si vous pouvez ici est une approche:

select col1, array_agg(col2), ar 
from (SELECT a1.column_1 as col1, a2.column_1 as col2, 
      ARRAY_AGG(DISTINCT a1.column_2 ORDER BY a1.column_2) as ar 
     FROM agg_test a1 JOIN 
      agg_test a2 
      ON a1.column_2 = a2.column_2 AND a1.column_1 <> a2.column_1 
     WHERE a1.column_1 = 1 
     GROUP BY a1.column_1, a2.column_1 
    ) t 
group by col1, ar 

L'alternative est d'utiliser array_dims pour convertir les valeurs de tableau dans une chaîne.

+0

Merci, fonctionne parfaitement pour moi. – Przemek

2

Vous pouvez également essayer quelque chose comme ceci:

SELECT DISTINCT 
    a1.column_1, 
    ARRAY_AGG(a2.column_1) OVER ( PARTITION BY a1.column_1, ARRAY_AGG(DISTINCT a1.column_2 ORDER BY a1.column_2) ) AS "a2.column_1 agg", 
    ARRAY_AGG(DISTINCT a1.column_2 ORDER BY a1.column_2) 
FROM agg_test a1 
JOIN agg_test a2 ON a1.column_2 = a2.column_2 AND a1.column_1 a2.column_1 
WHERE a1.column_1 = 1 
GROUP BY a1.column_1, a2.column_1 
;

(. Mis en avant sont les parties qui sont différentes de la requête que vous avez posté votre question)

Le ci-dessus utilise une fenêtre ARRAY_AGG à combiner les valeurs de a2.column_1 avec les autres ARRAY_AGG, en utilisant le résultat de ce dernier comme l'un des critères de partitionnement. Sans le DISTINCT, il produirait deux lignes {4,5} pour votre exemple. Donc, DISTINCT est nécessaire pour éliminer les doublons.

Voici une démo SQL Fiddle: http://sqlfiddle.com/#!1/df5c3/4

Notez, cependant, que la fenêtre ARRAY_AGG ne peut pas avoir un ORDER BY comme son homologue "normal". Cela signifie que l'ordre des valeurs a2.column_1 dans la liste serait indéterminé, bien que dans la démo liée, il arrive que cela corresponde à celui de votre sortie attendue.