好的Postgres天才,我需要一些帮助。我试图绘制大量数据,并希望在发送到前端之前尽可能地在数据库中准备数据。我正在使用Postgres 9.6
我有一组这样的结果:
Source | Date
--------|------------
Email | 2017-06-01
Email | 2017-06-01
Email | 2017-06-03
Email | 2017-06-03
Email | 2017-06-03
Email | 2017-06-04
Email | 2017-06-06
Email | 2017-06-06
Email | 2017-06-07
Banner | 2017-06-01
Banner | 2017-06-02
Banner | 2017-06-03
....
我需要按天计算所有数据然后进行列化,如果日期为零,我需要进行零填充。
期望的结果:
Source | 2017-06-01 | 2017-06-02 | 2017-06-03 | ... | 2017-06-07
--------|-------------|-------------|-------------|------|------------
Email | 2 | 0 | 3 | ... | 1
Banner | 1 | 1 | ...
我希望这是有道理的,谢谢。
答案 0 :(得分:0)
您可以使用:
SELECT
*
FROM
crosstab(
$$
SELECT "Source", "Date"::text, count("Date")
FROM t
GROUP BY "Source", "Date"
ORDER BY "Source"
$$,
$$
SELECT cast(d as date)
FROM generate_series(date '2017-06-01', date '2017-06-10', interval '1 day') as s(d)
$$
) AS
(
"Source" text,
"2017-06-01" bigint,
"2017-06-02" bigint,
"2017-06-03" bigint,
"2017-06-04" bigint,
"2017-06-05" bigint,
"2017-06-06" bigint,
"2017-06-07" bigint,
"2017-06-08" bigint,
"2017-06-09" bigint,
"2017-06-10" bigint
) ;
哪个使用crosstab(text source_sql, text category_sql)
,特定于PostgreSQL并且需要tablefunc
扩展名,或者您可以使用"经典SQL数据透视":
SELECT
"Source"
,COUNT(CASE WHEN "Date" = '2017-06-01' THEN 1 END) AS "2017-06-01"
,COUNT(CASE WHEN "Date" = '2017-06-02' THEN 1 END) AS "2017-06-02"
,COUNT(CASE WHEN "Date" = '2017-06-03' THEN 1 END) AS "2017-06-03"
,COUNT(CASE WHEN "Date" = '2017-06-04' THEN 1 END) AS "2017-06-04"
,COUNT(CASE WHEN "Date" = '2017-06-05' THEN 1 END) AS "2017-06-05"
,COUNT(CASE WHEN "Date" = '2017-06-06' THEN 1 END) AS "2017-06-06"
,COUNT(CASE WHEN "Date" = '2017-06-07' THEN 1 END) AS "2017-06-07"
,COUNT(CASE WHEN "Date" = '2017-06-08' THEN 1 END) AS "2017-06-08"
,COUNT(CASE WHEN "Date" = '2017-06-09' THEN 1 END) AS "2017-06-09"
,COUNT(CASE WHEN "Date" = '2017-06-10' THEN 1 END) AS "2017-06-10"
FROM
t
GROUP BY
"Source"
ORDER BY
"Source" ;
Source | 2017-06-01 | 2017-06-02 | 2017-06-03 | 2017-06-04 | 2017-06-05 | 2017-06-06 | 2017-06-07 | 2017-06-08 | 2017-06-09 | 2017-06-10 :----- | ---------: | ---------: | ---------: | ---------: | ---------: | ---------: | ---------: | ---------: | ---------: | ---------: Banner | 1 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 Email | 2 | 0 | 3 | 1 | 0 | 2 | 1 | 0 | 0 | 0
两者都会返回相同的值,差异是第二个会给你' 0' 0第一个会给你' null'当没有可计算的值时。
dbfiddle here
答案 1 :(得分:0)
此查询可用于非周期性日期范围。
SELECT *
FROM CROSSTAB(
$$
SELECT id,
fdate::TEXT,
fveri
FROM tmp_table
WHERE fdate = '05.11.2020'
OR fdate = '08.11.2020'
OR fdate = '11.11.2020'
OR fdate = '14.11.2020'
OR fdate = '17.11.2020'
ORDER BY 1, 2
$$,
$$
SELECT CAST(m AS date) FROM generate_series( date '05.11.2020' , date '18.11.2020' , interval '3 day' ) m
$$
) AS tmp ( tmpid integer,
"201105" varchar(50),
"201108" varchar(50),
"201111" varchar(50),
"201114" varchar(50),
"201117" varchar(50)
)
https://dbfiddle.uk/?rdbms=postgres_9.6&fiddle=95f56c27456ffc389dfb071387d6bef5
样本取自佩奇