ในหลักฉันมีช่วงเวลาสองชนิด:
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"
แนวคิดคือการรับรายการสั่งซื้อของทุกการประทับเวลาด้วยผลรวมการหมุน "bitmasked" ของช่วงเวลาที่เปิดในแต่ละครั้งเพื่อประเมินเวลาการแสดงตน
ซอทำงานและให้ผลลัพธ์โดยประมาณแม้ว่าช่วงเวลาที่แตกต่างกันจะเท่ากันก็ตาม ไม่มีการใช้ดัชนีในตัวอย่างนี้
นี่เป็นวิธีที่เหมาะสมในการบรรลุภารกิจที่ถูกสอบสวนหรือมีวิธีที่สง่างามกว่านี้หรือไม่?
หากเกี่ยวข้องกับการตอบ: จำนวนข้อมูลจะมากถึงหนึ่งหมื่นชุดข้อมูลต่อพนักงานต่อตาราง sql-2012 ใช้งานไม่ได้ในการคำนวณผลรวมสะสมของรุ่นก่อนหน้าแบบอินไลน์รวม
แก้ไข:
เพียงแค่เรียกใช้คิวรีกับ testdata ในปริมาณที่มากขึ้น (1,000, 10.000, 100.000, 1 ล้าน) และจะเห็นว่า runtime นั้นเพิ่มขึ้นแบบทวีคูณ เห็นได้ชัดว่ามีธงคำเตือนใช่ไหม
ฉันเปลี่ยนเคียวรีและลบการรวมของการรวมการกลิ้งโดยการอัปเดตที่แปลกประหลาด
ฉันได้เพิ่มตารางเสริม:
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"
รันไทม์ลดลงเหลือ 3 วินาทีสำหรับรายการ 1 ล้านรายการใน "worktime" -table
คำถามยังคงเหมือนเดิม : วิธีที่มีประสิทธิภาพที่สุดในการแก้ปัญหานี้คืออะไร
[this]
ในโลกของฉันที่ทำมักจะมีวงเล็บแล้วเช่น ฉันชอบที่ดีกว่าคำพูดสองเท่าฉันเดา