2

PostgreSQL に以下を含むテーブルがあります。

id   name   arrayofparents
1     First
2     Second      {1}
3     Second_Sec  {1,2}
4     Third       {1,2,3}
5     Second_A    {1}
6     Other
7     Trash       {6}

arrayofparentsinteger[]正しい順序でその行の親レコードのリストを含むタイプです。

id=4親は次のとおりです FirstSecondSecond_sec

特定の ID に対して親の名前の文字列を生成するクエリを作成するにはどうすればよいですか?

例えば:

id=3: First->Second.

id=4: First->Second->Second_sec.

id=7: Other.

編集: 可能であれば、要求されたIDnameが常に表示されることを好みます。 id=3: First->Second->Second_sec.

id=4: First->Second->Second_sec->Third.

id=7: Other->Trash.

id=6: Other.

4

3 に答える 3

2

generate_subscripts や array などの複数の操作を組み合わせて結果を取得できます。

with mtab as (
      SELECT id, name, array_append(arrayofparents,id) as arrayofparents,
      generate_subscripts(array_append(arrayofparents, id), 1) AS p_id FROM tab where id=2
)
select distinct array_to_string(
  array(
    select tab.name from tab join mtab t on tab.id=t.arrayofparents[t.p_id]
  ), '->'
) ;

実際の例 Sqfiddle

または外部結合を次のいずれかと組み合わせて使用​​します。

SELECT coalesce(string_agg(p.name, '->') || '->' || t.name, t.name) AS parentnames
FROM tab AS t
  LEFT JOIN tab AS p ON p.id = ANY(t.arrayofparents)
 where t.id =7 
GROUP BY t.id, t.name

実際の例 Sqfiddle

于 2015-12-06T09:04:00.280 に答える
1

これらの各クエリは、テーブル全体だけでなく、単一の ID に対しても機能します。
また、パス/フルパスまたは他のすべての列のみを返すこともできます。

SELECT t.*, concat_ws('->', t1.path, t.name) AS full_path
FROM   tbl t
LEFT   JOIN LATERAL (
   SELECT string_agg(t1.name, '->' ORDER  BY i) AS path
   FROM   generate_subscripts(t.arrayofparents, 1) i
   JOIN   tbl t1 ON t1.id = t.arrayofparents[i]   
   ) t1 ON true
WHERE  t.id = 4;  -- optional

または、サブクエリに移動することもできますORDER BY- 少し速いかもしれません:

SELECT concat_ws('->', t1.path, t.name) AS full_path
FROM   tbl t, LATERAL (
   SELECT string_agg(t1.name, '->') AS path
   FROM  (
      SELECT t1.name
      FROM   generate_subscripts(t.arrayofparents, 1) i
      JOIN   tbl t1 ON t1.id = t.arrayofparents[i]
      ORDER  BY i
      ) t1
   ) t1
WHERE  t.id = 4;  -- optional

集計はサブクエリで行われるため、外側のクエリにステップLATERALは必要ありません。GROUP BY

サブクエリは集計関数により常に行を返すため、NULL または空のLEFT JOIN LATERAL ... ON trueすべての行を保持する必要もありません。Postgres 9.3が必要です。arrayofparentsLATERAL
LATERAL

concat_ws()連結で可能な NULL 値を無視するために使用します。

SQL フィドル。

WITH OTDINALITYPostgres 9.4では少しシンプルで高速になります:

SELECT t.*, concat_ws('->', t1.path, t.name) AS full_path
FROM   tbl t, LATERAL (
   SELECT string_agg(t1.name, '->' ORDER BY ord) AS path
   FROM   unnest(t.arrayofparents) WITH ORDINALITY a(id,ord)
   JOIN   tbl t1 USING (id)  
   ) t1
WHERE  t.id = 4;

詳細な説明:


UNION ALLpg 9.3 のバリアント

SELECT t1.full_path
FROM   tbl t, LATERAL (
   SELECT string_agg(name, '->') AS full_path
   FROM  (
      (
      SELECT name
      FROM   generate_subscripts(t.arrayofparents, 1) i
      JOIN   tbl ON id = t.arrayofparents[i]
      ORDER  BY i
      )
      UNION ALL SELECT t.name
      ) t1
   ) t1
WHERE  t.id = 4;
于 2015-12-06T13:12:14.447 に答える
0

直接の親 (祖父母ではない) のみが必要な場合は、次のようなものが機能するはずです。

SELECT c.id, c.name, string_agg(p.name, '->') AS parentnames
FROM yourtable AS c
  LEFT JOIN yourtable AS p ON p.id = ANY c.parents
GROUP BY c.id, c.name
于 2015-12-06T08:41:01.520 に答える