sql - 从查询数据创建列

标签 sql postgresql crosstab

测试数据:

create temp table l (id integer,name text);
create temp table t (id integer);
create temp table t_i18n(id integer,l_id integer,t_id integer,name text);
insert into l(id, name) values
(1, 'lang_1'),
(2, 'lang_2');
insert into t(id) values(1);
insert into t_i18n(id, l_id, t_id, name) values 
(1, 1, 1, 'Text in the language one'),
(2, 2, 1, 'Text in the language two');

执行此查询后:

select *
from t
inner join t_i18n i18n
on i18n.t_id = t.id;

我有这样的结果:

 id | id | l_id | t_id |           name           
----+----+------+------+--------------------------
  1 |  1 |    1 |    1 | Text in the language one  
  1 |  2 |    2 |    1 | Text in the language two

是否可以修改上面的查询以获得下面的结果?

/*Expected result*/
 id | name_lang_1              | name_lang_2
----+--------------------------+--------------------------
  1 | Text in the language one | Text in the language two

最佳答案

通常 crosstab() 是最快的。您需要附加模块 tablefunc安装在您的数据库中。

SELECT * FROM crosstab(
   'SELECT t.id, l.name AS lang_name, i.name AS lang
    FROM   t
    JOIN   t_i18n i ON i.t_id = t.id
    JOIN   l  ON l.id = i.l_id'  -- could also just be "ORDER BY 1" here

   ,$$VALUES ('lang_1'::text), ('lang_2')$$)
AS l (id text, lang_1 text, lang_2 text);

如果您的案例实际上就这么简单(几乎从来没有),使用 CASE 语句的查询就可以:

SELECT t.id
      , min(CASE WHEN i.l_id = 1 THEN i.name ELSE NULL END) AS lang_1
      , min(CASE WHEN i.l_id = 2 THEN i.name ELSE NULL END) AS lang_2
FROM               t
LEFT   JOIN t_i18n i ON i.t_id = t.id
LEFT   JOIN        l ON l.id = i.l_id
GROUP  BY 1
ORDER  BY 1;

此相关问题下两种解决方案的详细信息:
PostgreSQL Crosstab Query

由于每个 SQL 查询和每个函数都必须具有明确定义的返回类型,因此不可能在单个查询中对动态数量的语言名称执行此操作。您可以编写一个函数来动态创建语句并在第二次调用中执行该语句。

还有多态类型的高级技术,我在这里写了一个全面的答案:
Dynamic alternative to pivot with CASE and GROUP BY

但是,上面的简单 crosstab() 查询可以很好地处理语言名称的超集。不存在的语言的字段返回 NULL。看看 provided link .

关于sql - 从查询数据创建列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17882523/

相关文章:

ruby-on-rails - Active Record 查询 JSONB 列上存储数组中的第一个值

sql - 具有三列的 PostgreSQL 交叉表,其中值从一列求和

mysql - sql查询从另一个表的输入中提取数据

php - MySQL 查询上周获得前 10 名积分的人?

MySQL : How to get records are have non null values?

r - 按数据集中的外观对交叉表的列和行进行排序

python - Groupby 值对数据框 pandas 的计数

sql - WHERE 子句中的 HIVE SQL 子查询

postgresql - 不能使用 uuid 并创建一个扩展来使用它

javascript - 将带有毫秒的unix时间戳转换为postgres可读的timestamptz