我正在尝试在 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;
这是结果
标签 | 数 |
---|---|
50 | |
西班牙 | 23 |
法国 | 99 |
我想做的是旋转这个表来得到这个结果
西班牙 | 法国 | |
---|---|---|
50 | 23 | 99 |
有人有解决办法吗? 感谢您的回答。
编辑:
忘了说,我可能有更多或更少的国家,具体取决于我请求的数据库,并且我需要它适用于相同的查询
您可以使用 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);
我希望这可以帮助你。
您可以通过 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 擅长对数据进行任何切片,但在格式化结果方面却很差。您的演示管理器只需将垂直结果集转换为水平结果集。它应该在这方面表现出色。
请参阅演示;