考虑PostgreSQL 9.4中的以下事件数据:
eventTime | eventName
2015-09-25 18:00:00 | 'AAA'
2015-09-25 17:00:00 | 'BBB'
2015-09-25 16:00:00 | 'BBB'
2015-09-25 15:00:00 | 'BBB'
2015-09-25 14:00:00 | 'AAA'
2015-09-26 13:00:00 | 'CCC'
2015-09-26 12:00:00 | 'AAA'
2015-09-26 11:00:00 | 'BBB'
2015-09-26 10:00:00 | 'CCC'
2015-09-26 09:00:00 | 'BBB'
2015-09-27 08:00:00 | 'AAA'
2015-09-27 07:00:00 | 'CCC'
2015-09-27 05:00:00 | 'CCC'
2015-09-27 04:00:00 | 'CCC'
2015-09-27 03:00:00 | 'CCC'
2015-09-27 02:00:00 | 'AAA'
虽然基于单count()
的表很简单,例如:
SELECT eventTime, count(1)
from (SELECT data->>'eventName' as eventName,
date_trunc('day', to_timestamp(data->>'timestamp','YYYY-MM-DDZHH24:MI:SS.MS')::timestamp without time zone) AS eventTime
FROM sidetrack where (data->>'eventName' = 'AAA') IS TRUE) AS tmptab
GROUP BY eventTime
ORDER BY eventTime ASC
只能计算单个值eventName
的出现次数。我对SQL不太熟悉,并且很难找到创建双向频率表的方法。在这个例子中,结果将是:
day | 'AAA' | 'BBB' | 'CCC'
------------+-------+-------+-------
2015-09-25 | 2 | 3 | 0
2015-09-26 | 1 | 2 | 2
2015-09-27 | 2 | 0 | 4
有些例子会计算具有数值的变量
使用with_bucket()
,但不会将其推广到字符串值字段。
我在WITH
下尝试过嵌套选择,例如:
WITH
foo AS (
SELECT ...
),
bar AS (
SELECT ...
FROM foo
),
SELECT *
FROM bar;
使用外部JOINS,但我无法解决这个问题。
答案 0 :(得分:1)
你可以为每一列使用一个CASE语句为匹配生成1,然后将所有行都用于SUM,类似于;
SELECT date_trunc('day', timestamp) AS time,
SUM(CASE WHEN "eventName" = 'AAA' THEN 1 ELSE 0 END) AAA,
SUM(CASE WHEN "eventName" = 'BBB' THEN 1 ELSE 0 END) BBB,
SUM(CASE WHEN "eventName" = 'CCC' THEN 1 ELSE 0 END) CCC
FROM sidetrack
GROUP BY date_trunc('day', timestamp)
ORDER BY date_trunc('day', timestamp) ASC
答案 1 :(得分:1)
此查询选择每天的事件计数:
select day, event, count(*)
from (
select
left(date_trunc('day', (data->>'timestamp')::timestamp)::text, 10) as day,
data->>'eventName' as event
from sidetrack
) s
group by 1, 2
order by 1 asc, 2;
day | event | count
------------+-------+-------
2015-09-25 | AAA | 2
2015-09-25 | BBB | 3
2015-09-26 | AAA | 1
2015-09-26 | BBB | 2
2015-09-26 | CCC | 2
2015-09-27 | AAA | 2
2015-09-27 | CCC | 4
(7 rows)
您可以在crosstab()
功能中使用查询:
create extension if not exists tablefunc;
select * from crosstab (
$q$
select day, event, count(*)
from (
select
left(date_trunc('day', (data->>'timestamp')::timestamp)::text, 10) as day,
data->>'eventName' as event
from sidetrack
) s
group by 1, 2
order by 1 asc
$q$,
$q$
values ('AAA'), ('BBB'), ('CCC')
$q$)
as ct (day text, "AAA" int, "BBB" int, "CCC" int);
day | AAA | BBB | CCC
------------+-----+-----+-----
2015-09-25 | 2 | 3 |
2015-09-26 | 1 | 2 | 2
2015-09-27 | 2 | | 4
(3 rows)