Ben bu bir SQL Server bilgimin sınırlarını tükenmiş düşünüyorum.
SQL sunucusunda bir boşluk bulmak için (C # kodunun yaptığı şey) ve boşlukları (ilk başlatmadan önce veya son bitişten sonra olanlar) başlatmayı veya sonlandırmayı umursamıyorsanız, aşağıdaki sorgu (veya değişkenler) bulabildiğim en hızlı:
SELECT e.FinishedAt as GapStart, s.StartedAt as GapEnd
FROM
(
SELECT StartedAt, ROW_NUMBER() OVER (ORDER BY StartedAt) AS rn
FROM dbo.Tasks
) AS s
INNER JOIN
(
SELECT FinishedAt, ROW_NUMBER() OVER (ORDER BY FinishedAt) + 1 AS rn
FROM dbo.Tasks
) AS e ON e.rn = s.rn and s.StartedAt > e.FinishedAt
Her bir başlangıç-bitiş seti için, başlangıç ve bitişe ayrı diziler olarak davranabilir, bitişi bir dengeleyebilir ve boşluklar gösterilebilir.
örneğin (S1, F1), (S2, F2), (S3, F3) 'i alın ve şu şekilde sıralayın: {S1, S2, S3, null} ve {null, F1, F2, F3}. her sette ve boşluklar F set değerinin S set değerinden daha az olduğu yerlerdir ... sorun bence SQL sunucusunda iki ayrı seti birleştirmek veya sadece değerlerin sırasına göre karşılaştırmak mümkün değildir. küme ... dolayısıyla satır_sayısı işlevinin tamamen satır numarasına dayalı olarak birleştirmemizi sağlamak için kullanılması ... ancak SQL sunucusuna bu değerlerin benzersiz olduğunu söylemenin bir yolu yoktur (bunları bir indekse sahip bir tabloya eklemeden) üzerinde - hangisi daha uzun sürer - denedim), bu yüzden birleştirme birleşimi en iyi olduğunu düşünüyorum? (yapabileceğim her şeyden daha hızlı olduğunu kanıtlamak zor olsa da)
LAG / LEAD işlevlerini kullanarak çözümler elde edebildim:
select * from
(
SELECT top (100) percent StartedAt, FinishedAt, LEAD(StartedAt, 1, null) OVER (Order by FinishedAt) as NextStart
FROM dbo.Tasks
) as x
where NextStart > FinishedAt
(bu arada, sonuçları garanti etmiyorum - işe yarıyor gibi görünüyor, ancak sanırım Görevler tablosunda sıralı olmaya başladım ... ve daha yavaştı)
Toplam değişikliğini kullanma:
select * from
(
SELECT EventTime, Change, SUM(Change) OVER (ORDER BY EventTime, Change desc ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) as RunTotal --, x.*
FROM
(
SELECT StartedAt AS EventTime, 1 AS Change
FROM dbo.Tasks
UNION ALL
SELECT FinishedAt AS EventTime, -1 AS Change
FROM dbo.Tasks
) AS TaskEvents
) as x
where x.RunTotal = 0 or (x.RunTotal = 1 and x.Change = 1)
ORDER BY EventTime, Change DESC
(sürpriz değil, aynı zamanda daha yavaş)
Hatta bir CLR toplama işlevi denedim (toplamı değiştirmek için - toplamdan daha yavaştı ve verilerin sırasını korumak için row_number () kullanıldı) ve CLR (iki sonuç kümesini açmak ve değerleri tamamen temel alan değerleri karşılaştırmak için) ve daha yavaştı. SQL ve CLR sınırlamalarında kafamı birçok kez denedim, birçok yöntemi denedim
Ve ne için?
Aynı makinede çalışan ve hem C # verilerini hem de SQL filtrelenmiş verileri bir dosyaya tükürmek (orijinal C # koduna göre), zamanlar neredeyse aynıdır ... 1 boşluk verileri için yaklaşık 2 saniye (C # genellikle daha hızlı ), Çoklu boşluk veri kümesi için 8-10 saniye (SQL genellikle daha hızlıdır).
NOT : SQL Server Geliştirme Ortamı zamanlama karşılaştırması için kullanmayın, çünkü ızgaraya gösterilmesi zaman alır. SQL 2012, VS2010, .net 4.0 İstemci profili ile test edildiği gibi
Her iki çözümün de SQL sunucusundaki verilerin aynı sıralama işlemini gerçekleştirdiğine dikkat çekeceğim, böylece getirme sıralaması için sunucu yükü benzer olacaktır, hangi çözümü kullanırsanız kullanın, tek fark istemcideki (sunucu yerine) işlemdir. ve ağ üzerinden aktarım.
Farklı personel üyeleri tarafından bölümleme yaparken veya boşluk bilgileriyle ekstra verilere ihtiyaç duyabildiğinizde (ne bir personel kimliği dışında başka bir şey düşünemesem de) ne fark olabilir, ya da tabii ki orada bir olduğunu yavaş SQL sunucusu ve istemci makine (veya arasındaki veri bağlantısı yavaş istemci) ... Ne de birden fazla kullanıcı için kilit zamanlarda veya çekişme sorunları veya CPU / AĞ konularda bir karşılaştırmasını yaptık ... Bu yüzden hangisinin bu durumda bir darboğaz olması daha muhtemel olduğunu bilmiyorum.
Ne biliyorum, evet, SQL Server bu tür küme karşılaştırmaları iyi değil ve sorguyu doğru yazmazsanız bunun için ödeyecek.
C # sürümünü yazmaktan daha mı kolay ya da zor mu? Tamamen emin değilim, Değişim +/- 1, toplam çözümü çalıştıran da tamamen sezgisel değil ve ben ama ortalama bir mezunun geleceği ilk çözüm değil ... bir kez yapıldığında kopyalamak yeterince kolay, ama ilk etapta yazmak içgörü gerektirir ... aynı SQL versiyonu için de söylenebilir. Hangisi daha zor? Hangisi haydut verilere daha dayanıklı? Hangisi paralel işlemler için daha fazla potansiyele sahiptir? Programlama çabasına kıyasla farkın ne kadar küçük olduğu gerçekten önemli mi?
Son bir not; veriler üzerinde belirtilmemiş bir kısıtlama vardır - StartedAt, FinishedAt değerinden daha az olmalıdır , aksi takdirde kötü sonuçlar alırsınız.