2012-04-08 15 views
5

मेरे पास एक श्रृंखला है (आईपी वर्कर (15), डेटटाइम डेटाटाइम 2) मान। प्रत्येक पंक्ति उपयोगकर्ता द्वारा किए गए HTTP अनुरोध से मेल खाती है। मैं इन पंक्तियों में सत्र संख्या असाइन करना चाहता हूं। विभिन्न आईपी पते में अलग-अलग सत्र संख्याएं होती हैं। यदि अंतिम अनुरोध 30min से पुराना है तो एक ही आईपी को एक नया सत्र संख्या असाइन किया जाना चाहिए।एसक्यूएल सर्वर: row_number timout द्वारा विभाजित

IP,  DateTime,   SessionNumber, RequestNumber 
1.1.1.1, 2012-01-01 00:01, 1,    1 
1.1.1.1, 2012-01-01 00:02, 1,    2 
1.1.1.1, 2012-01-01 00:03, 1,    3 
1.1.1.2, 2012-01-01 00:04, 2,    1 --different IP => new session number 
1.1.1.2, 2012-01-01 00:05, 2,    2 
1.1.1.2, 2012-01-01 00:40, 3,    1 --same IP, but last request 35min ago (> 30min) 

कॉलम 1 और 2 आदानों, 3 और 4 वांछित outputs रहे हैं: यहां एक नमूना उत्पादन होता है। तालिका दो उपयोगकर्ताओं को दिखाती है।

अंतर्निहित तालिका तालिका काफी बड़ी है, इसे कुशलता से हल किया जा सकता है? मैं डेटा (एक या दो) पर पास की एक छोटी निरंतर राशि पसंद करूंगा।

+0

SQL सर्वर का कौन सा संस्करण? यदि 2012 नई 'ओवर' क्लॉज कार्यक्षमता मदद करेगा। –

+0

हां, यह SQL सर्वर 2012 है। – usr

उत्तर

8

यहां कुछ प्रयास हैं।

;WITH CTE1 AS 
(
SELECT *, 
IIF(DATEDIFF(MINUTE, 
     LAG(DateTime) OVER (PARTITION BY IP ORDER BY DateTime), 
     DateTime) < 30,0,1) AS SessionFlag 
FROM Sessions 
), CTE2 AS 
(
SELECT *, 
     SUM(SessionFlag) OVER (PARTITION BY IP 
            ORDER BY DateTime) AS IPSessionNumber 
FROM CTE1 
) 
SELECT IP, 
     DateTime, 
     DENSE_RANK() OVER (ORDER BY IP, IPSessionNumber) AS SessionNumber, 
     ROW_NUMBER() OVER (PARTITION BY IP, IPSessionNumber 
           ORDER BY DateTime) AS RequestNumber 
FROM CTE2 

यह (IP, IPSessionNumber से तो IP, DateTime द्वारा) दो तरह कार्य किया है लेकिन/30 मिनट ग्रहण करता है कि SessionNumber एक अलग अद्वितीय सत्र संख्या आईपी पते के अनुसार प्रत्येक नए सत्र के लिए असाइन किया गया है के रूप में मनमाने ढंग से जब तक सौंपा जा सकता है राज करते हैं।

क्रोनोलॉजिकल क्रम में SessionNumber क्रमशः असाइन करने के लिए। मैंने निम्नलिखित का इस्तेमाल किया।

;WITH CTE1 AS 
(
SELECT *, 
IIF(DATEDIFF(MINUTE, 
     LAG(DateTime) OVER (PARTITION BY IP ORDER BY DateTime), 
     DateTime) < 30,0,1) AS SessionFlag 
FROM Sessions 
), CTE2 AS(
SELECT *, 
     SUM(SessionFlag) OVER (ORDER BY DateTime) AS GlobalSessionNo 
FROM CTE1 
), CTE3 AS(
SELECT *, 
     MAX(CASE WHEN SessionFlag = 1 THEN GlobalSessionNo END) 
       OVER (PARTITION BY IP ORDER BY DateTime) AS SessionNumber 
FROM CTE2) 
SELECT IP, 
     DateTime, 
     SessionNumber, 
     ROW_NUMBER() OVER (PARTITION BY SessionNumber 
           ORDER BY DateTime) AS RequestNumber 
FROM CTE3 

इससे क्रमशः संचालन की संख्या 4 हो जाती है।

+0

यदि दो आईपी के इंटरलीव से अनुरोध, तो क्या उनके सत्र मिश्रण नहीं होंगे? – Andomar

+0

@Andomar - अच्छा बिंदु! फिक्स्ड। –

+0

खिड़की की गिनती का उपयोग करना सरल है! मुझे वह चाल याद आएगी। – usr

2

यहां एक आईडी बनाने के लिए एक तालिका चर और row_number का उपयोग कर एक संस्करण है जिसका उपयोग रिकर्सिव सीटीई में किया जा सकता है। कर्सर के खिलाफ प्रदर्शन और मार्टिन द्वारा प्रदान की गई एक क्वेरी (मार्टिन द्वारा प्रदान किए गए) संस्करणों की तुलना करना उचित हो सकता है।

CREATE TABLE #T 
(
    IP varchar(15), 
    DateTime datetime, 
    ID int, 
    primary key (IP, ID) 
) 

insert into #T(IP, DateTime, ID) 
select IP, DateTime, row_number() over(partition by IP order by DateTime) 
from #sessionRequests 

;with C as 
(
    select IP, 
     ID, 
     DateTime, 
     1 as Session 
    from #T 
    where ID = 1 
    union all 
    select T.IP, 
     T.ID, 
     T.DateTime, 
     C.Session + case when datediff(minute, C.DateTime, T.DateTime) >= 30 then 1 else 0 end 
    from #T as T 
    inner join C 
     on T.IP = C.IP and 
     T.ID = C.ID + 1 
) 
SELECT IP, 
     DateTime, 
     dense_rank() over(order by IP, Session) as SessionNumber, 
     row_number() over(partition by IP, Session order by DateTime) as RequestNumber 
from C 
order by IP, DateTime, SessionNumber, RequestNumber 
option (maxrecursion 0) 
+1

मुझे यह संस्करण पसंद है क्योंकि यह कर्सर आधारित दृष्टिकोण की तरह विस्तार करना आसान है। मैंने इसे एक अस्थायी तालिका का उपयोग करने के लिए बदल दिया जो ऑप्टिमाइज़र समस्या को ठीक करता है (तालिका चर के आंकड़े नहीं हैं)। साथ ही, मैंने सत्यापित किया है कि यह कोड काम करता है। धन्यवाद! – usr

संबंधित मुद्दे