पर प्रत्येक बिंदु पर सबसे हालिया संस्करण ढूंढें, मैं दिनांक अंतराल के एक सेट के साथ काम कर रहा हूं जहां प्रत्येक अंतराल में संस्करण संख्या होती है और नए अंतराल अक्सर पुराने लोगों को ओवरलैप करते हैं, या यहां तक कि उनके सबसेट भी हो। इस डेटा से मुझे अंतराल के एक नए सेट की गणना करने की आवश्यकता है जो प्रत्येक बिंदु पर सबसे हालिया संस्करण संख्या दिखाता है। क्या इस समस्या का एक सेट-आधारित समाधान है?ओवरलैपिंग के एक सेट में, संस्करण-क्रमांकित अंतराल,
Interval 1: 11111111111111111111111
Interval 2: 2222222222
Interval 3: 33333333333333
Interval 4: 444444444
Interval 5: 555555555
Result : 11333333333333331155555555544
यहाँ डेटा का एक नमूना के साथ मैं काम कर रहा हूँ है:
यहाँ एक उदाहरण दिया गया है
groupId startDate endDate version
-------- --------- ---------- ------
1 1/1/2010 1/1/2011 1
1 10/1/2010 7/5/2011 2
1 7/5/2011 8/13/2012 3
1 8/13/2012 12/31/2012 6
1 10/1/2012 11/1/2012 8
... और वांछित उत्पादन:
groupId startDate endDate version
-------- --------- ---------- ------
1 1/1/2010 10/1/2010 1
1 10/1/2010 7/5/2011 2
1 7/5/2011 8/13/2012 3
1 8/13/2011 10/1/2012 6
1 10/1/2012 11/1/2012 8 << note how version 8 supersedes version 6
1 11/1/2012 12/31/2012 6 << version 6 is split into two records
मुझे इस समस्या का कोई अन्य उदाहरण नहीं मिला है, मेरा गुगल केवल उन प्रश्नों को बदलता है जो gaps and islands याकी पहचान करते हैं।
मुझे लगता है कि मेरे पास एक पुनरावृत्ति समाधान (SQL सर्वर 2008) है। यह परिणाम सेट में अंतराल के लिए एक अस्थायी तालिका से शुरू होता है और उस सीमा के लिए प्रारंभ और अंत बिंदु को परिभाषित करता है जिसे हम विशेष संस्करण संख्याओं के साथ रिकॉर्ड डालने के द्वारा कवर करना चाहते हैं। फिर, यह बार-बार परिणाम निर्धारित अंतराल के बीच अंतराल को दिखाता है और, उन्हें मूल डेटा सेट से सबसे हाल ही रिकॉर्ड के साथ भरने के लिए प्रयास करता है, जब तक वहाँ कोई और अधिक अंतराल या कोई और अधिक रिकॉर्ड जोड़ने के लिए कर रहे हैं:
GO
-- Create data set and results table
CREATE TABLE #Data (
groupId INT
,startDate DATE
,endDate DATE
,versionId INT
)
INSERT INTO #Data (groupId, startDate, endDate, versionId) VALUES (1, '2007-12-22', '2008-12-22', 8)
INSERT INTO #Data (groupId, startDate, endDate, versionId) VALUES (1, '2008-12-22', '2009-12-22', 9)
INSERT INTO #Data (groupId, startDate, endDate, versionId) VALUES (1, '2009-12-22', '2010-12-22', 10)
INSERT INTO #Data (groupId, startDate, endDate, versionId) VALUES (1, '2010-12-22', '2011-12-22', 11)
INSERT INTO #Data (groupId, startDate, endDate, versionId) VALUES (1, '2011-01-01', '2011-11-30', 500)
INSERT INTO #Data (groupId, startDate, endDate, versionId) VALUES (1, '2011-12-22', '2012-12-22', 12)
INSERT INTO #Data (groupId, startDate, endDate, versionId) VALUES (1, '2012-01-22', '2012-12-22', 13)
INSERT INTO #Data (groupId, startDate, endDate, versionId) VALUES (1, '2012-01-22', '2012-12-22', 14)
INSERT INTO #Data (groupId, startDate, endDate, versionId) VALUES (1, '2012-04-22', '2012-12-22', 17)
INSERT INTO #Data (groupId, startDate, endDate, versionId) VALUES (1, '2012-04-22', '2012-12-22', 19)
INSERT INTO #Data (groupId, startDate, endDate, versionId) VALUES (2, '2010-01-01', '2011-01-01', 1)
INSERT INTO #Data (groupId, startDate, endDate, versionId) VALUES (2, '2010-10-01', '2011-07-05', 2)
INSERT INTO #Data (groupId, startDate, endDate, versionId) VALUES (2, '2011-07-05', '2012-08-13', 3)
INSERT INTO #Data (groupId, startDate, endDate, versionId) VALUES (2, '2012-08-13', '2012-12-31', 6)
INSERT INTO #Data (groupId, startDate, endDate, versionId) VALUES (2, '2012-10-01', '2012-11-01', 8)
CREATE TABLE #Results (
groupId VARCHAR(10)
,startDate DATE
,endDate DATE
,versionId BIGINT
)
DECLARE @startDate DATE
DECLARE @endDate DATE
DECLARE @placeholderId BIGINT
SET @startDate = '20030101'
SET @endDate = '20121231'
SET @placeholderId = 999999999999999
INSERT #Results
SELECT DISTINCT
groupId
,CASE WHEN MIN(startDate) < @startDate THEN MIN(startDate) ELSE @startDate END
,CASE WHEN MIN(startDate) < @startDate THEN @startDate ELSE MIN(startDate) END
,@placeholderId
FROM #data
GROUP BY groupId
UNION ALL
SELECT DISTINCT
groupId
,CASE WHEN MAX(endDate) < @endDate THEN MAX(endDate) ELSE @endDate END
,CASE WHEN MAX(endDate) < @endDate THEN @endDate ELSE MAX(endDate) END
,@placeholderId
FROM #data
GROUP BY groupId
GO
-- Fill gaps in results table
DECLARE @startDate DATE
DECLARE @endDate DATE
DECLARE @placeholderId BIGINT
SET @startDate = '20030101'
SET @endDate = '20111231'
SET @placeholderId = 999999999999999
DECLARE @counter INT
SET @counter = 0
WHILE @counter < 10
BEGIN
SET @counter = @counter + 1;
WITH Gaps AS (
SELECT
gs.groupId
,gs.startDate
,MIN(ge.endDate) as endDate
,ROW_NUMBER() OVER (ORDER BY gs.groupId, gs.startDate) as gapId
FROM (
SELECT groupId, endDate as startDate
FROM #Results r1
WHERE NOT EXISTS (
SELECT *
FROM #Results r2
WHERE r2.groupId = r1.groupId
AND r2.versionId <> r1.versionId
AND r2.startDate <= r1.endDate
AND r2.endDate > r1.endDate
)
AND NOT (endDate >= @endDate AND versionId = @placeholderId)
) gs
INNER JOIN (
SELECT groupId, startDate as endDate
FROM #Results r1
WHERE NOT EXISTS (
SELECT *
FROM #Results r2
WHERE r2.groupId = r1.groupId
AND r2.versionId <> r1.versionId
AND r2.endDate >= r1.startDate
AND r2.startDate < r1.startDate
)
AND NOT (startDate <= @startDate AND versionId = @placeholderId)
) ge
ON ge.groupId = gs.groupId
AND ge.endDate >= gs.startDate
GROUP BY gs.groupId, gs.startDate
)
INSERT #Results (
groupId
,startDate
,endDate
,versionId
)
SELECT
d.groupId
,CASE WHEN d.startDate < g.startDate THEN g.startDate ELSE d.startDate END
,CASE WHEN d.endDate > g.endDate THEN g.endDate ELSE d.endDate END
,d.versionId
FROM #Data d
INNER JOIN Gaps g
ON g.groupId = d.groupId
AND g.startDate <= d.endDate
AND g.endDate >= d.startDate
INNER JOIN (
SELECT
d.groupId
,gapId
,MAX(d.versionId) as versionId
FROM #Data d
INNER JOIN Gaps g
ON g.groupId = d.groupId
AND g.startDate <= d.endDate
AND g.endDate >= d.startDate
WHERE d.versionId < (
SELECT MIN(versionId)
FROM #Results r
WHERE r.groupId = d.groupId
AND (r.startDate = g.endDate OR r.endDate = g.startDate)
)
AND NOT EXISTS (
SELECT *
FROM #Data dsup
WHERE dsup.groupId = d.groupId
AND dsup.versionId > d.versionId
AND dsup.startDate <= d.startDate
AND dsup.endDate >= d.endDate
)
GROUP BY
d.groupId
,g.gapId
) mg
ON mg.groupId = g.groupId
AND mg.gapId = g.gapId
AND mg.versionId = d.versionId
END
SELECT *
FROM #Results
WHERE versionId <> @placeholderId
order by groupId, startDate
एक सेट के आधार पर समाधान अधिक उपयोगी होगा, लेकिन मैंने एक खोजने के लिए संघर्ष किया है। कोई विचार?
http://sqlfiddle.com/#!6/94431/1 – Laurence
के लिए धन्यवाद त्वरित प्रतिक्रिया! परीक्षण डेटा के साथ दौड़ें, परिणाम बहुत अच्छा लग रहा है। मैं इसे बाद में अपने बड़े डेटा सेट के साथ चलाऊंगा और अपने पुनरावर्तक समाधान और आपके बहु-क्वेरी समाधान के लिए प्रदर्शन परिणाम पोस्ट करूंगा। – ExcelValdez
यदि संस्करणों में अंतराल हो सकता है, तो समाप्ति दिनांक गणना विफल हो जाती है। यह है, उदाहरण डेटा में ऐसा नहीं होता है, हालांकि: http://sqlfiddle.com/#!6/ec8dc/1 – Laurence