我有一张表格列出了建筑物内所有人的登记和结账信息。 我的目标是计算在特定时间(如每小时)在建筑物中有多少人。
这是我的表:
CREATE TABLE checkins
(
date_in DateTime,
date_out DateTime,
age Int32,
sex String,
date_day Date MATERIALIZED toDate(date_in)
) ENGINE = MergeTree(date_day, date_in, 8192)
示例数据
INSERT INTO checkins VALUES
(toDateTime('2018-01-01 08:30:00'), toDateTime('2018-01-01 16:30:00'), 32, 'M'),
(toDateTime('2018-01-01 09:30:00'), toDateTime('2018-01-01 10:30:00'), 28, 'M'),
(toDateTime('2018-01-01 10:15:00'), toDateTime('2018-01-01 10:45:00'), 30, 'M'),
(toDateTime('2018-01-01 11:30:00'), toDateTime('2018-01-01 11:45:00'), 35, 'M'),
(toDateTime('2018-01-01 14:30:00'), toDateTime('2018-01-01 17:30:00'), 25, 'F');
我目前正在以这种方式计算建筑物内的人数:
SELECT count(*), instant
FROM
(
SELECT arrayJoin([toDateTime('2018-01-01 10:00:00'), toDateTime('2018-01-01 12:00:00'), toDateTime('2018-01-01 14:00:00'), toDateTime('2018-01-01 16:00:00')] AS tabinstants) AS instant
FROM checkins
WHERE (date_in < instant) AND (date_out > instant)
)
GROUP BY instant
ORDER BY instant ASC
按预期返回
┌─count()─┬─────────────instant─┐
│ 2 │ 2018-01-01 10:00:00 │
│ 1 │ 2018-01-01 12:00:00 │
│ 1 │ 2018-01-01 14:00:00 │
│ 2 │ 2018-01-01 16:00:00 │
└─────────┴─────────────────────┘
然而,这个请求似乎不具有可扩展性:它在数组和表中的行中有很多点时非常慢。我假设这是因为连接数据的大小。是否有一种机制可以更有效地计算这些数据?
第二个问题: 如果我现在想要在每个点之间拥有最大人数,我该怎么办?
e.g。 在10:00到12:00之间我最多有3个人(10:15)
┌─count()─┬─────────────instant─┐
│ 3 │ 2018-01-01 10:00:00 │
│ 1 │ 2018-01-01 12:00:00 │
│ 2 │ 2018-01-01 14:00:00 │
│ 2 │ 2018-01-01 16:00:00 │
└─────────┴─────────────────────┘
答案 0 :(得分:0)
您可以尝试运算符timeSlots
,它会生成30分钟的数组。
arrayFilter
可以过滤小时数,因此您将拥有小时数。
所以你的查询将是这样的
SELECT count(*), instant
FROM
(
SELECT arrayJoin(arrayFilter(x -> toStartOfHour(x) = x, timeSlots(toDateTime('2018-01-01 08:00:00'), toUInt32(toDateTime('2018-01-01 20:00:00') - toDateTime('2018-01-01 08:00:00')))) AS tabinstants) AS instant
FROM checkins
WHERE (toStartOfHour(date_in) <= instant) AND (toStartOfHour(date_out) + 3600 > instant)
)
GROUP BY instant
ORDER BY instant ASC