连接类型为“的postgresql表”;VarChar数组";?

连接类型为“的postgresql表”;VarChar数组";?,postgresql,Postgresql,直到大约5分钟前,我还不知道你得到了一个VARCHAR类型,它也是一个数组。我将如何连接这些表: PEOPLE ID | PERSON | GROUPS 1 | John | {ONE,TWO} 2 | Jack | {TWO} 3 | Jill | {ONE,TWO,THREE} 4 | Jim | {TWO,THREE} GROUPS ID | TITLE ONE | First TWO | Second THREE | Third 我想以这样的方

直到大约5分钟前,我还不知道你得到了一个VARCHAR类型,它也是一个数组。我将如何连接这些表:

PEOPLE
ID | PERSON | GROUPS
1  | John   | {ONE,TWO}
2  | Jack   | {TWO}
3  | Jill   | {ONE,TWO,THREE}
4  | Jim    | {TWO,THREE}

GROUPS
ID    | TITLE
ONE   | First
TWO   | Second
THREE | Third
我想以这样的方式结束:

ID | PERSON | GROUP
1  | John   | ONE
1  | John   | TWO
2  | Jack   | TWO
3  | Jill   | ONE
3  | Jill   | TWO
3  | Jill   | THREE
4  | Jim    | TWO
4  | Jim    | THREE

如何在一个查询中正确执行此操作?

对于该特定查询,有一个使用
unnest()
的语法技巧,它允许在select语句中将一行扩展为多行:

select id, person, unnest(groups) as grp
from people
我猜你真的希望第一,第二,第三个出现,而不是一个,两个或三个。您可以这样加入:

with unnested_people as (
select id, person, unnest(groups) as grp
from people
)
select id, person, title
from unnested_people
join groups on groups.id = unseated_people.grp

unest
在这里是不必要的,您可以使用一个简单的连接来测试数组成员资格:

SELECT people."ID", people."PERSON", groups."ID"
FROM people
INNER JOIN groups ON groups."ID" = ANY (people."GROUPS")
ORDER BY people."ID", groups."ID";
见:

(奇怪的上半部是因为我懒得修复SQLFiddle不一致的标识符引用。它引用列名,但不引用表名。)

您甚至可以在
people.GROUPS
上使用GIN索引并获得索引联接。GIN索引的构建成本不低,更新成本也很高,所以您只需要在真正需要时才想这样做,但它很有用。请参阅有关数组索引的手册。例如:

CREATE INDEX people_groups_gin_idx ON people USING GIN("GROUPS");

SELECT people."ID", people."PERSON", groups."ID"
FROM people
INNER JOIN groups ON ARRAY[groups."ID"] @> people."GROUPS"
ORDER BY people."ID", groups."ID";

不管谁否决了这一点,他都应该亲自测试并看到语法技巧的效果相当好,例如,
select1作为a,unnest({2,3}::int[])作为b绝对是我要找的东西!:)请注意我刚才报告的错误::-)我没有投反对票,但你为什么称之为“把戏”,因为这是某种东西。。。隐藏?@Denis它不是一只虫子,尽管它确实很丑。由于可怕的历史原因,
SELECT
列表中的set返回函数被定义为以这种方式工作。现在9.3有了真正的
横向
支持,我希望我们可以在9.4中选择一个
警告
中创建SRF。