मुख्य में, मुझे दो प्रकार के समय अंतराल मिले हैं:
presence time
तथा absence time
absence time
विभिन्न प्रकार के हो सकते हैं (जैसे विराम, अनुपस्थिति, विशेष दिन वगैरह) और समय अंतराल ओवरलैप और / या इंटरसेक्ट हो सकते हैं।
यह सुनिश्चित करने के लिए नहीं है, कि कच्चे डेटा में अंतराल के केवल प्रशंसनीय संयोजन मौजूद हैं, जैसे। अतिव्यापी उपस्थिति-अंतराल का कोई मतलब नहीं है, लेकिन मौजूद हो सकता है। मैंने अब कई तरीकों से परिणामी उपस्थिति-समय अंतराल की पहचान करने की कोशिश की है - मेरे लिए, सबसे आरामदायक एक follwing लगता है।
;with "timestamps"
as
(
select
"id" = row_number() over ( order by "empId", "timestamp", "opening", "type" )
, "empId"
, "timestamp"
, "type"
, "opening"
from
(
select "empId", "timestamp", "type", case when "types" = 'starttime' then 1 else -1 end as "opening" from
( select "empId", "starttime", "endtime", 1 as "type" from "worktime" ) as data
unpivot ( "timestamp" for "types" in ( "starttime", "endtime" ) ) as pvt
union all
select "empId", "timestamp", "type", case when "types" = 'starttime' then 1 else -1 end as "opening" from
( select "empId", "starttime", "endtime", 2 as "type" from "break" ) as data
unpivot ( "timestamp" for "types" in ( "starttime", "endtime" ) ) as pvt
union all
select "empId", "timestamp", "type", case when "types" = 'starttime' then 1 else -1 end as "opening" from
( select "empId", "starttime", "endtime", 3 as "type" from "absence" ) as data
unpivot ( "timestamp" for "types" in ( "starttime", "endtime" ) ) as pvt
) as data
)
select
T1."empId"
, "starttime" = T1."timestamp"
, "endtime" = T2."timestamp"
from
"timestamps" as T1
left join "timestamps" as T2
on T2."empId" = T1."empId"
and T2."id" = T1."id" + 1
left join "timestamps" as RS
on RS."empId" = T2."empId"
and RS."id" <= T1."id"
group by
T1."empId", T1."timestamp", T2."timestamp"
having
(sum( power( 2, RS."type" ) * RS."opening" ) = 2)
order by
T1."empId", T1."timestamp";
कुछ डेमो डेटा के लिए SQL-Fiddle देखें ।
कच्चे डेटा के रूप में अलग-अलग तालिकाओं में मौजूद "starttime" - "endtime"
या "starttime" - "duration"
।
यह विचार था कि उपस्थिति समय का अनुमान लगाने के लिए प्रत्येक टाइमस्टैम्प की खुली सूची में एक "बिटमास्क" रोलिंग अंतराल के साथ एक आदेशित सूची प्राप्त की जाए।
फ़िडल काम करता है और अनुमानित परिणाम देता है, भले ही विभिन्न अंतरालों की शुरुआत समान हो। इस उदाहरण में किसी भी सूचकांक का उपयोग नहीं किया गया है।
क्या यह सही कार्य को प्राप्त करने का सही तरीका है या इसके लिए और अधिक सुरुचिपूर्ण तरीका है?
यदि उत्तर देने के लिए प्रासंगिक है: डेटा की मात्रा प्रति टेबल प्रति कर्मचारी दस-हज़ार डेटासेट तक होगी। एग्रीगेट में पूर्ववर्ती इनलाइन की रोलिंग राशि की गणना करने के लिए sql-2012 उपलब्ध नहीं है।
संपादित करें:
बस टेस्टाटाटा (1000, 10.000, 100.000, 1 मिलियन) की बड़ी राशि के खिलाफ क्वेरी को निष्पादित किया और देख सकते हैं कि रनटाइम तेजी से बढ़ता है। जाहिर है एक चेतावनी झंडा, सही?
मैंने क्वेरी को बदल दिया और क्वर्की अपडेट द्वारा रोलिंग योग के एकत्रीकरण को हटा दिया।
मैंने एक सहायक तालिका जोड़ी है:
create table timestamps
(
"id" int
, "empId" int
, "timestamp" datetime
, "type" int
, "opening" int
, "rolSum" int
)
create nonclustered index "idx" on "timestamps" ( "rolSum" ) include ( "id", "empId", "timestamp" )
और मैंने इस स्थान पर रोलिंग योग की गणना की:
declare @rolSum int = 0
update "timestamps" set @rolSum = "rolSum" = @rolSum + power( 2, "type" ) * "opening" from "timestamps"
रनटाइम "वर्कटाइम" -योग्य में 1 मिलियन प्रविष्टियों के बारे में 3 सेकंड तक कम हो गया।
प्रश्न समान है : इसे हल करने का सबसे प्रभावी तरीका क्या है?
[this]
। मुझे लगता है कि डबल कोट्स की तुलना में बेहतर है, मुझे लगता है।