【问题标题】:Pivot table on postgresqlpostgresql 上的数据透视表
【发布时间】:2021-12-30 07:45:03
【问题描述】:

我正在尝试在 postgresql 数据库上创建一个表,但我无法成功。 这是我最初的要求

SELECT tag_country.label, COUNT(*)
FROM log_event_tracking LEFT JOIN user_account ON log_event_tracking.email = user_account.email LEFT JOIN tag_country ON user_account.country = tag_country.id
WHERE date_time > CURRENT_DATE - INTERVAL '7 days'
GROUP BY tag_country.label;

这是结果

label count
<null> 50
Spain 23
France 99

我想要做的是旋转这个表来得到这个结果

<null> Spain France
50 23 99

有人有解决办法吗? 感谢您的回答。

编辑:

忘了说我可能有更多国家或更少国家,具体取决于我请求的数据库,我需要它与相同的查询一起使用

【问题讨论】:

标签: postgresql pivot-table crosstab


【解决方案1】:

你可以使用tablefunc扩展中的函数crosstab,我这里举个例子来使用。

如果不存在,则需要在此处创建 tablefunc 扩展

CREATE EXTENSION IF NOT EXISTS tablefunc;

CREATE TABLE exams (
     id bigserial NOT NULL,
     name text,
     exam int,
     score int,
     PRIMARY KEY (id)
);

insert into exams (name,exam,score) values ('Bob',1,70);
insert into exams (name,exam,score) values ('Bob',2,77); 
insert into exams (name,exam,score) values ('Bob',3,71);
insert into exams (name,exam,score) values ('Bob',4,70);

insert into exams (name,exam,score) values ('Sue',1,89);
insert into exams (name,exam,score) values ('Sue',2,87);
insert into exams (name,exam,score) values ('Sue',3,88);
insert into exams (name,exam,score) values ('Sue',4,89);

现在您可以运行查询,将其转换为数据透视表,您可以在附图中看到结果。

SELECT * FROM crosstab('select name, exam, score from exams order by 1,2')
         AS ct (name text,exam1 int, exam2 int, exam3 int, exam4 int);

result for pivot table

希望对你有所帮助。

【讨论】:

  • 您好,谢谢您的回答,这正是我想要做的。只有一件事不同:我正在尝试通过动态数量的考试来做到这一点。有没有办法指示交叉表有(名称文本,考试...... int)或类似的东西
  • 您好@BenoitBonavia,您能分享您的查询或表格模型以更好地阐明我的理解吗?
【解决方案2】:

您可以使用 SQL 获得所需的内容。但是我建议你问的不是一个好主意,它涉及大量维护的方式只是为了保持查询的准确性而没有任何其他好处。但首先,如何做到这一点。好吧,tablefunc 建议会起作用,另一个选择是 Postgres filter 子句。

select "<null>", "France", "Spain"
  from ( 
        select count(*) filter (where label is null) as "<null>"
             , count(*) filter (where label = 'France') as "France"
             , count(*) filter (where label = 'Spain')  as "Spain"
          from tag_country             
       ) sq;

问题在于,您必须在运行查询之前知道确切的数据透视列,并在进行修改时进行更新。因此,如果您有更多国家或更少国家,具体取决于我请求的数据库并且我需要它与相同的查询一起使用,则无法实现。您的选择是更新查询或编写相关过程以动态生成 SQL :( 或将透视推到应用程序中的表示层。查询变成一个简单的计数:

select label, count(*)
  from tag_country 
 group by label
 order by label nulls first;

SQL 擅长对数据进行切片,但在格式化结果方面却很差。您的演示经理只需要将垂直结果集转换为水平结果集。它应该擅长。

demo

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-04
    • 1970-01-01
    • 1970-01-01
    • 2016-02-26
    • 2014-01-04
    相关资源
    最近更新 更多