Sons comme une application pour les fonctions de fenêtre . Mais, malheureusement, ce n'est pas le cas. Les cadres de fenêtre ne peuvent être basés que sur le nombre de lignes, pas sur les valeurs réelles des colonnes.
Une requête simple avec LEFT JOIN
peut faire le travail :
SELECT t0.order_id
, count(t1.time_created) AS count_within_3_sec
FROM tbl t0
LEFT JOIN tbl t1 ON t1.time_created BETWEEN t0.time_created - interval '3 sec'
AND t0.time_created
GROUP BY 1
ORDER BY 1;
db<>violon ici
Ne fonctionne pas avec time
comme dans votre démo minimale, car cela ne tourne pas rond. Je suppose qu'il est raisonnable de supposer timestamp
ou timestamptz
.
Puisque vous incluez chaque ligne elle-même dans le décompte, un INNER JOIN
fonctionnerait aussi. (LEFT JOIN
est encore plus fiable face à d'éventuelles valeurs NULL.)
Ou utilisez un LATERAL
sous-requête et vous n'avez pas besoin d'agréger au niveau de la requête externe :
SELECT t0.order_id
, t1.count_within_3_sec
FROM tbl t0
LEFT JOIN LATERAL (
SELECT count(*) AS count_within_3_sec
FROM tbl t1
WHERE t1.time_created BETWEEN t0.time_created - interval '3 sec'
AND t0.time_created
) t1 ON true
ORDER BY 1;
Connexe :
Pour les grandes tables et de nombreuses lignes dans le laps de temps, une solution procédurale qui parcourt la table une fois sera plus performant. Comme :
- Fonctions de fenêtre ou expressions de tableau communes :compter les lignes précédentes dans la plage
- Alternatives au PL/ruby cassé :convertir une table de journal d'entrepôt
- GROUPER PAR et agréger valeurs numériques séquentielles