মূলত, আমি দুই ধরণের সময়ের ব্যবধান পেয়েছি:
presence time
এবং absence time
absence time
বিভিন্ন ধরণের (যেমন বিরতি, অনুপস্থিতি, বিশেষ দিন এবং তাই) হতে পারে এবং সময়ের ব্যবধানগুলি ওভারল্যাপ এবং / বা ছেদ করতে পারে।
এটি নিশ্চিতভাবে নয় যে কাঁচা ডেটাতে কেবল বিরতিগুলির মধ্যে কেবল প্রশ্রয়জনক সংমিশ্রণ বিদ্যমান। ওভারল্যাপিং উপস্থিতি-বিরতিগুলি বোঝায় না, তবে এটি উপস্থিত থাকতে পারে। আমি এখন অনেক উপায়ে ফলাফল উপস্থিতি সময়ের ব্যবধানগুলি সনাক্ত করার চেষ্টা করেছি - আমার কাছে, সবচেয়ে আরামদায়ক মনে হচ্ছে ফলউইং এক।
;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";
কিছু ডেমো ডেটার জন্য এসকিউএল-ফিডল দেখুন ।
কাঁচা ডেটা বিভিন্ন আকারে "starttime" - "endtime"
বা আকারে বিদ্যমান "starttime" - "duration"
।
উপস্থিতির সময়টি অনুমান করার জন্য প্রতিটি সময়ে "বিটমাস্কড" রোলিং সমষ্টি সহ প্রতিটি টাইমস্ট্যাম্পের একটি অর্ডারযুক্ত তালিকা পাওয়ার ধারণা ছিল।
বিভিন্ন বিরতিতে স্টারটাইম সমান হলেও, ফিডাল কাজ করে এবং আনুমানিক ফলাফল দেয়। এই উদাহরণে কোনও সূচক ব্যবহার করা হয় না।
এটি কি প্রশ্নযুক্ত কার্য অর্জনের সঠিক উপায় বা এর জন্য আরও মার্জিত কোনও উপায় আছে?
যদি উত্তর দেওয়ার জন্য প্রাসঙ্গিক হয়: তথ্যের পরিমাণ প্রতি টেবিল প্রতি কর্মচারী বেশ কয়েক দশ-হাজার ডেটাসেট পর্যন্ত হবে। সামগ্রিকভাবে ইনলাইন পূর্বসূরীদের রোলিং যোগফল গণনা করার জন্য স্কুয়েল -২০১২ উপলভ্য নয়।
সম্পাদনা:
সর্বাধিক পরিমাণ টেস্টডাটা (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]
। আমার মনে হয় ডাবল উক্তিগুলির চেয়ে এটি আরও ভাল।