अस्वीकरण:मैं अपना उत्तर निम्नलिखित (उत्कृष्ट) पोस्ट के आधार पर लिख रहा हूँ:
https://www.itprotoday.com/sql-server/calculating-concurrent-sessions-part-3 (भाग 1 और 2 की भी सिफारिश की जाती है)
उस समस्या के साथ यहां समझने वाली पहली बात यह है कि इंटरनेट में पाए जाने वाले अधिकांश मौजूदा समाधानों में मूल रूप से दो मुद्दे हो सकते हैं
- परिणाम सही उत्तर नहीं है (उदाहरण के लिए यदि श्रेणी ए, बी और सी के साथ ओवरलैप होती है लेकिन बी सी के साथ ओवरलैप नहीं होती है तो वे 3 ओवरलैपिंग रेंज के रूप में गिना जाता है)।
- इसकी गणना करने का तरीका बहुत अक्षम है (क्योंकि O(n^2) है और / या वे इस अवधि में प्रत्येक सेकंड के लिए चक्कर लगाते हैं)
समाधान में सामान्य प्रदर्शन समस्या, जैसे कि अनरेसन्स द्वारा प्रस्तावित, एक कुदरती समाधान है, प्रत्येक कॉल के लिए आपको अन्य सभी कॉलों की जांच करनी होगी यदि वे ओवरलैप हैं।
एक एल्गोरिथम रैखिक सामान्य समाधान है जो सभी "घटनाओं" (प्रारंभ कॉल और समाप्ति कॉल) को सूचीबद्ध करता है, और एक शुरुआत के लिए 1 जोड़ें और हैंग-अप के लिए 1 को घटाएं, और अधिकतम याद रखें। इसे कर्सर के साथ आसानी से कार्यान्वित किया जा सकता है (हाफोर द्वारा प्रस्तावित समाधान उस तरह से प्रतीत होता है) लेकिन कर्सर समस्याओं को हल करने के सबसे प्रभावी तरीके नहीं हैं।
संदर्भित लेख में उत्कृष्ट उदाहरण, विभिन्न समाधान, उनके प्रदर्शन की तुलना है। प्रस्तावित समाधान है:
WITH C1 AS
(
SELECT starttime AS ts, +1 AS TYPE,
ROW_NUMBER() OVER(ORDER BY starttime) AS start_ordinal
FROM Calls
UNION ALL
SELECT endtime, -1, NULL
FROM Calls
),
C2 AS
(
SELECT *,
ROW_NUMBER() OVER( ORDER BY ts, TYPE) AS start_or_end_ordinal
FROM C1
)
SELECT MAX(2 * start_ordinal - start_or_end_ordinal) AS mx
FROM C2
WHERE TYPE = 1
स्पष्टीकरण
मान लीजिए डेटा का यह सेट
+-------------------------+-------------------------+
| starttime | endtime |
+-------------------------+-------------------------+
| 2009-01-01 00:02:10.000 | 2009-01-01 00:05:24.000 |
| 2009-01-01 00:02:19.000 | 2009-01-01 00:02:35.000 |
| 2009-01-01 00:02:57.000 | 2009-01-01 00:04:04.000 |
| 2009-01-01 00:04:12.000 | 2009-01-01 00:04:52.000 |
+-------------------------+-------------------------+
यह एक प्रश्न के साथ एक ही विचार को लागू करने का एक तरीका है, कॉल की प्रत्येक शुरुआत के लिए 1 जोड़ना और प्रत्येक समाप्ति के लिए 1 घटाना।
SELECT starttime AS ts, +1 AS TYPE,
ROW_NUMBER() OVER(ORDER BY starttime) AS start_ordinal
FROM Calls
C1 CTE का यह भाग प्रत्येक कॉल का प्रत्येक प्रारंभ समय लेगा और इसे नंबर देगा
+-------------------------+------+---------------+
| ts | TYPE | start_ordinal |
+-------------------------+------+---------------+
| 2009-01-01 00:02:10.000 | 1 | 1 |
| 2009-01-01 00:02:19.000 | 1 | 2 |
| 2009-01-01 00:02:57.000 | 1 | 3 |
| 2009-01-01 00:04:12.000 | 1 | 4 |
+-------------------------+------+---------------+
अब यह कोड
SELECT endtime, -1, NULL
FROM Calls
पंक्ति क्रमांकन के बिना सभी "अंतिम समय" उत्पन्न करेगा
+-------------------------+----+------+
| endtime | | |
+-------------------------+----+------+
| 2009-01-01 00:02:35.000 | -1 | NULL |
| 2009-01-01 00:04:04.000 | -1 | NULL |
| 2009-01-01 00:04:52.000 | -1 | NULL |
| 2009-01-01 00:05:24.000 | -1 | NULL |
+-------------------------+----+------+
अब यूनियन को पूर्ण C1 CTE परिभाषा बनाने के लिए, आपके पास दोनों टेबल मिश्रित होंगे
+-------------------------+------+---------------+
| ts | TYPE | start_ordinal |
+-------------------------+------+---------------+
| 2009-01-01 00:02:10.000 | 1 | 1 |
| 2009-01-01 00:02:19.000 | 1 | 2 |
| 2009-01-01 00:02:57.000 | 1 | 3 |
| 2009-01-01 00:04:12.000 | 1 | 4 |
| 2009-01-01 00:02:35.000 | -1 | NULL |
| 2009-01-01 00:04:04.000 | -1 | NULL |
| 2009-01-01 00:04:52.000 | -1 | NULL |
| 2009-01-01 00:05:24.000 | -1 | NULL |
+-------------------------+------+---------------+
C2 की गणना एक नए कॉलम के साथ C1 को क्रमबद्ध और क्रमांकित करने के लिए की जाती है
C2 AS
(
SELECT *,
ROW_NUMBER() OVER( ORDER BY ts, TYPE) AS start_or_end_ordinal
FROM C1
)
+-------------------------+------+-------+--------------+
| ts | TYPE | start | start_or_end |
+-------------------------+------+-------+--------------+
| 2009-01-01 00:02:10.000 | 1 | 1 | 1 |
| 2009-01-01 00:02:19.000 | 1 | 2 | 2 |
| 2009-01-01 00:02:35.000 | -1 | NULL | 3 |
| 2009-01-01 00:02:57.000 | 1 | 3 | 4 |
| 2009-01-01 00:04:04.000 | -1 | NULL | 5 |
| 2009-01-01 00:04:12.000 | 1 | 4 | 6 |
| 2009-01-01 00:04:52.000 | -1 | NULL | 7 |
| 2009-01-01 00:05:24.000 | -1 | NULL | 8 |
+-------------------------+------+-------+--------------+
और वह जगह है जहां जादू होता है, किसी भी समय #start - #ends का परिणाम इस समय सहवर्ती कॉल की मात्रा है।
प्रत्येक प्रकार =1 (प्रारंभ घटना) के लिए हमारे पास तीसरे कॉलम में #start मान है। और हमारे पास #start + #end (चौथे कॉलम में)
. भी है#start_or_end = #start + #end
#end = (#start_or_end - #start)
#start - #end = #start - (#start_or_end - #start)
#start - #end = 2 * #start - #start_or_end
तो SQL में:
SELECT MAX(2 * start_ordinal - start_or_end_ordinal) AS mx
FROM C2
WHERE TYPE = 1
इस मामले में कॉल के प्रस्तावित सेट के साथ, परिणाम 2 है।
प्रस्तावित लेख में, उदाहरण के लिए एक सेवा या "फोन कंपनी" या "फोन सेंट्रल" द्वारा समूहीकृत परिणाम प्राप्त करने के लिए थोड़ा सुधार किया गया है और इस विचार का उपयोग समूह के लिए भी किया जा सकता है उदाहरण के लिए समय स्लॉट द्वारा और अधिकतम समरूपता है किसी दिए गए दिन में घंटे के हिसाब से।