प्रत्येक समय सीमा के अंत (या प्रारंभ) से 30 मिनट घटाएं। फिर मूल रूप से मेरे संदर्भित "सरल" उत्तर में बताए अनुसार आगे बढ़ें। (हर जगह सही दिशा में 30 मिनट के लिए समायोजन)। 30 मिनट से कम की रेंज को एक प्राथमिकता से हटा दिया जाता है - जो समझ में आता है क्योंकि वे कभी भी 30 मिनट की निरंतर ओवरलैप की अवधि का हिस्सा नहीं हो सकते हैं। साथ ही क्वेरी को तेज़ बनाता है।
अक्टूबर 2019 में सभी दिनों के लिए गणना (उदाहरण श्रेणी):
WITH range AS (SELECT timestamp '2019-10-01' AS start_ts -- incl. lower bound
, timestamp '2019-11-01' AS end_ts) -- excl. upper bound
, cte AS (
SELECT userid, starttime
-- default to current timestamp if NULL
, COALESCE(endtime, localtimestamp) - interval '30 min' AS endtime
FROM usersessions, range r
WHERE starttime < r.end_ts -- count overlaps *starting* in outer time range
AND (endtime >= r.start_ts + interval '30 min' OR endtime IS NULL)
)
, ct AS (
SELECT ts, sum(ct) OVER (ORDER BY ts, ct) AS session_ct
FROM (
SELECT endtime AS ts, -1 AS ct FROM cte
UNION ALL
SELECT starttime , +1 FROM cte
) sub
)
SELECT ts::date, max(session_ct) AS max_concurrent_sessions
FROM ct, range r
WHERE ts >= r.start_ts
AND ts < r.end_ts -- crop outer time range
GROUP BY ts::date
ORDER BY 1;
db<>fiddle यहां
ध्यान रखें कि LOCALTIMESTAMP
वर्तमान सत्र के समय क्षेत्र पर निर्भर करता है। अपनी तालिका में टाइमस्टैम्प्ज़ और CURRENT_TIMESTAMP
. का उपयोग करने पर विचार करें बजाय। देखें: