我被一个查询困住了:
CREATE TABLE public.bulk_sample (
serial_number character varying(255),
validation_date timestamp, -- timestamp of entry and exit
station_id integer,
direction integer -- 1 = Entry | 2 = Exit
);
INSERT INTO public.bulk_sample VALUES
('019b5526970fcfcf7813e9fe1acf8a41bcaf5a5a5c10870b3211d82f63fbf270', '2020-02-01 08:31:58', 120, 1)
, ('019b5526970fcfcf7813e9fe1acf8a41bcaf5a5a5c10870b3211d82f63fbf270', '2020-02-01 08:50:22', 113, 2)
, ('019b5526970fcfcf7813e9fe1acf8a41bcaf5a5a5c10870b3211d82f63fbf270', '2020-02-01 10:16:56', 113, 1)
, ('019b5526970fcfcf7813e9fe1acf8a41bcaf5a5a5c10870b3211d82f63fbf270', '2020-02-01 10:47:06', 120, 2)
, ('019b5526970fcfcf7813e9fe1acf8a41bcaf5a5a5c10870b3211d82f63fbf270', '2020-02-01 16:02:12', 120, 1)
, ('019b5526970fcfcf7813e9fe1acf8a41bcaf5a5a5c10870b3211d82f63fbf270', '2020-02-01 16:47:45', 102, 2)
, ('019b5526970fcfcf7813e9fe1acf8a41bcaf5a5a5c10870b3211d82f63fbf270', '2020-02-01 19:26:38', 102, 1)
, ('019b5526970fcfcf7813e9fe1acf8a41bcaf5a5a5c10870b3211d82f63fbf270', '2020-02-01 20:17:24', 120, 2)
, ('23cc9678e8cf834decb096ba36be0efee418402bce03aab52e69026adfec7663', '2020-02-01 07:58:20', 119, 1)
, ('23cc9678e8cf834decb096ba36be0efee418402bce03aab52e69026adfec7663', '2020-02-01 08:43:35', 104, 2)
, ('23cc9678e8cf834decb096ba36be0efee418402bce03aab52e69026adfec7663', '2020-02-01 16:38:10', 104, 1)
, ('23cc9678e8cf834decb096ba36be0efee418402bce03aab52e69026adfec7663', '2020-02-01 17:15:01', 119, 2)
, ('23cc9678e8cf834decb096ba36be0efee418402bce03aab52e69026adfec7663', '2020-02-01 17:42:29', 119, 1)
, ('23cc9678e8cf834decb096ba36be0efee418402bce03aab52e69026adfec7663', '2020-02-01 17:48:05', 120, 2)
, ('2a8f28bf0afc655210aa337aff016d33100282ac73cca660a397b924808499af', '2020-02-01 15:17:59', 120, 1)
, ('2a8f28bf0afc655210aa337aff016d33100282ac73cca660a397b924808499af', '2020-02-01 15:25:25', 118, 2)
, ('2a8f28bf0afc655210aa337aff016d33100282ac73cca660a397b924808499af', '2020-02-01 16:16:12', 118, 1)
, ('2a8f28bf0afc655210aa337aff016d33100282ac73cca660a397b924808499af', '2020-02-01 16:32:51', 120, 2)
, ('2a8f28bf0afc655210aa337aff016d33100282ac73cca660a397b924808499af', '2020-02-01 19:31:20', 120, 1)
, ('2a8f28bf0afc655210aa337aff016d33100282ac73cca660a397b924808499af', '2020-02-01 19:39:33', 118, 2)
, ('2a8f28bf0afc655210aa337aff016d33100282ac73cca660a397b924808499af', '2020-02-01 20:57:50', 118, 1)
, ('2a8f28bf0afc655210aa337aff016d33100282ac73cca660a397b924808499af', '2020-02-01 21:16:25', 120, 2)
;
我必须创建一个查询,其结果如下
source | dest | Count
120 | 113 | 1
113 | 120 | 1
我尝试了以下代码,但无法获得所需的结果:
SELECT serial_number
, count(*)
, min(validation_date) AS start_time
, CASE WHEN count(*) > 1 THEN max(validation_date) END AS end_time
FROM (
SELECT serial_number, validation_date, count(step OR NULL) OVER (ORDER BY serial_number,
validation_date) AS grp
FROM (
SELECT *
, lag(validation_date) OVER (PARTITION BY serial_number ORDER BY validation_date)
< validation_date - interval '60 min' AS step
FROM table1
where BETWEEN '2020-02-01 00:00:00' AND '2020-02-01 23:59:59'
) sub1
) sub2
GROUP BY serial_number, grp;
每次进出之间的时间间隔约为 55 分钟至 60 分钟。
我也尝试过内部联接,但无法按内部联接中的时间间隔进行分组
SELECT source.station_id AS source_station ,dest.station_id AS destination_station ,source.count FROM
(
SELECT serial_number,station_id,count(bulk_transaction_id) FROM table1
WHERE
direction = 1 AND
validation_date BETWEEN '2020-02-01 00:00:00' AND '2020-02-01 23:59:59'
GROUP BY serial_number,station_id
)source
INNER JOIN
(
SELECT serial_number,station_id,count(bulk_transaction_id) FROM table1
WHERE
direction = 2 AND
validation_date BETWEEN '2020-02-01 00:00:00' AND '2020-02-01 23:59:59'
GROUP BY serial_number,station_id
)dest
ON source.serial_number = dest.serial_number and source.station_id <> dest.station_id
挑战有时是进入日期为空,有时退出日期为空。
为此,您将需要两件事:
之后,您的查询变为:
应该返回:
这应该是最简单和最快的,而每个事务
serial_number
从不重叠:db<>在这里摆弄
① 我重写了
WHERE
条件,以最佳方式获得 2020 年 2 月 1 日的所有内容。BETWEEN
几乎总是时间范围的错误工具。看:此外,当时间分量丢失时,假定“2020-02-01”是一个完全有效的
timestamp
常数。00:00:00
在检索给定时间范围内的结果时,一个普通的 btree索引是
(validation_date)
最佳的。对于完整的表,索引(serial_number, validation_date)
会更有帮助。validation_date IS NULL
?查询继续工作,而在给定时间范围内只有最后一个目的地有,因为值碰巧按默认升序排列在最后。但它与. 您必须更仔细地定义这些可以弹出的位置以及如何准确处理它们。
serial_number
validation_date IS NULL
NULL
validation_date IS NULL
(2x)
uuid
而不是varchar(255)
forserial_number
?您
serial_number
似乎是一个正好有 64 位数字的十六进制数。如果是这样,varchar(255)
是一个糟糕的选择。看:此外,一个
uuid
(32 个十六进制数字)就足够了。如果需要所有 64 个十六进制数字,仍然考虑 2uuid
列。更小、更快、更安全。考虑:db<>在这里摆弄
看: