2011-06-07 17 views
5

- मैंने जो संपादन जोड़ा है, उसके लिए नीचे स्क्रॉल करें -एसक्यूएल सर्वर - समान रिकॉर्ड के समूह से हाल के रिकॉर्ड का चयन करें

तो मेरा परिदृश्य यहां है। मेरे पास एक सारणी है जिसमें हर बार किसी डेटा में कोई बदलाव करने के लिए प्रवेश होता है। इसका कारण यह है कि हमें सभी परिवर्तनों का ऑडिट करने में सक्षम होना चाहिए।

हालांकि, मैं केवल उपयोगकर्ता द्वारा बनाए गए संपादनों की एक श्रृंखला के लिए नवीनतम रिकॉर्ड पुनर्प्राप्त करना चाहता हूं।

तो चलो वहाँ तीन उपयोगकर्ताओं, उपयोगकर्ता ए, बी और सी

उपयोगकर्ता एक 10 परिवर्तन (तालिका में 10 प्रविष्टियों) बनाता हैं मान लीजिए। उपयोगकर्ता B 5 में आता है बदल जाता उपयोगकर्ता एक बनाता है 3 और अधिक परिवर्तन उपयोगकर्ता C 2 बदल जाता

क्या मैं है वापस पाने के लिए चाहते हैं: अधिकांश 2 रिकॉर्ड सी अधिकांश 3 रिकॉर्ड की हाल ही में बनाई गई इस बात का हाल यह है कि एक बनाया अधिकांश 5 अभिलेखों का हाल यह है कि बी अधिकांश 10 रिकॉर्ड एक बनाया है कि

4 पंक्तियों है कि मैं वापस पाने के कुल के लिए की हाल ही में बनाई गई

यहाँ मैं क्या करने की कोशिश की है, लेकिन समस्या यह है कि है LastUpd जब RowNum 1 पर वापस नहीं जाता है atedBy परिवर्तन:

WITH cte AS 
(
    SELECT 
     [LastUpdatedOn] 
     ,[LastUpdatedBy] 
     ,ROW_NUMBER() OVER(PARTITION BY [LastUpdatedBy] ORDER BY [LastUpdatedOn] DESC) [RowNum] 
    FROM [HistoricalTable] 
)   
SELECT 
    [LastUpdatedOn] 
    ,[LastUpdatedBy] 
    ,RowNum 
FROM cte 
--WHERE RowNum = 1 
ORDER BY [LastUpdatedOn] DESC; 

और यहाँ उत्पादन मैं मिलता है

LastUpdatedOn LastUpdatedBy RowNum 
**2011-06-07 13:07:26.917 629 1** 
2011-06-07 12:57:53.700 629 2 
2011-06-07 12:57:44.387 629 3 
2011-06-07 12:57:34.913 629 4 
2011-06-07 12:57:25.040 629 5 
2011-06-07 12:57:19.927 629 6 
2011-06-07 12:55:17.460 629 7 
2011-06-07 12:55:12.287 629 8 
2011-06-07 12:30:34.377 629 9 
**2011-06-07 11:54:05.727 4 1** 
**2011-06-07 11:50:02.723 629 10** (If this number went back to 1, my query would have worked fine) 
2011-06-07 11:26:43.053 629 11 
2011-06-07 10:54:32.867 629 12 
2011-06-07 10:46:32.107 629 13 
2011-06-07 10:40:52.937 629 14 
**2011-06-07 10:39:50.880 3 1** 

(** तारक पंक्तियों मैं वापस चाहते हैं प्रतिनिधित्व करते हैं) ---------------- --- संपादित करें --------------------

तो मैं एक समाधान के साथ आया, लेकिन यह बहुत ही सुरुचिपूर्ण नहीं है और मुझे यकीन नहीं है कि मुझे यह पसंद है, लेकिन यह चाल है। यह आपको जो कुछ करने की कोशिश कर रहा है उसकी बेहतर समझ दे सकता है।

DECLARE @temp AS TABLE(LastUpdatedOn datetime, LastUpdatedBy int null, RowNum int); 

DECLARE @newTable AS TABLE(LastUpdatedOn datetime, LastUpdatedBy int null); 

DECLARE @lastUserId int = 0; 

INSERT INTO @temp 
SELECT 
    [LastUpdatedOn] 
    ,[LastUpdatedBy] 
    ,ROW_NUMBER() OVER(ORDER BY [LastUpdatedOn] DESC) [RowNum] 
    FROM [HistoricalTable] 

DECLARE @totalRecords int; 
SELECT @totalRecords = COUNT(*) FROM @temp; 
DECLARE @counter int = 0; 
WHILE @counter <= @totalRecords BEGIN 
    SET @counter = @counter + 1; 

    INSERT INTO @newTable 
    SELECT LastUpdatedOn, LastUpdatedBy 
    FROM @temp 
    WHERE RowNum = @counter AND (@lastUserId != LastUpdatedBy OR (LastUpdatedBy IS NULL)); 

    SELECT @lastUserId = LastUpdatedBy FROM @temp WHERE RowNum = @counter;  
END 

SELECT * FROM @newTable; 

और डेटा है कि लौटा दिया जाता है:

LastUpdatedOn LastUpdatedBy 
2011-06-07 13:07:26.917 629 
2011-06-07 11:54:05.727 4 
2011-06-07 11:50:02.723 629 
2011-06-07 10:39:50.880 3 
+0

यह क्वेरी (WHERE RowNum = 1 uncommented के साथ) वास्तव में आपको आवश्यक परिणाम देनी चाहिए ... चूंकि आप उपयोगकर्ता द्वारा निर्धारित परिणाम को विभाजित कर रहे हैं और फिर दिनांक के आधार पर डेटासेट को ऑर्डर कर रहे हैं, तो आपको शीर्षतम अपडेट अपडेट करना चाहिए जब आप RowNum = द्वारा रिकॉर्ड्स फ़िल्टर करते हैं तो प्रत्येक उपयोगकर्ता द्वारा 1. क्या आप एक बार फिर से सत्यापित कर सकते हैं? – Chandu

+0

आपके उदाहरण में, ए 10 परिवर्तन करता है और फिर ए 3 और परिवर्तन करता है। आपका कोड ए द्वारा किए गए सबसे हालिया परिवर्तन को वापस कर देगा। लेकिन आपका सवाल कहता है कि आप ए के बदलावों के लिए दो पंक्तियां चाहते हैं। दूसरे से एक बदलाव के पहले सेट में क्या अंतर होता है? – 8kb

+0

@ साइबरनेट - हां, अगर मैं इसे असम्बद्ध करता हूं तो यह रिकॉर्ड फ़िल्टर करेगा, लेकिन बिल्कुल सही नहीं है। यदि आप मेरा डेटा आउटपुट देखते हैं, तो आप देखेंगे कि यह उपयोगकर्ता 629 से उपयोगकर्ता 4 पर, फिर 629 पर कहां जाता है। जहां यह 629 पर फिर से जाता है, रोवनम 1 के बजाय 10 पर जाता है, और फिर मुझे यह रिकॉर्ड नहीं मिलेगा जिसकी मुझे आवश्यकता है। – Makotosan

उत्तर

4
;with cte as 
(
    select *, 
    row_number() over(order by LastUpdatedOn) as rn 
    from HistoricalTable 
) 
select C1.LastUpdatedOn, 
     C1.LastUpdatedBy 
from cte as C1 
    left outer join cte as C2 
    on C1.rn = C2.rn-1 
where C1.LastUpdatedBy <> coalesce(C2.LastUpdatedBy, 0) 

LastUpdatedOn हुए प्रत्येक पंक्ति आदेश के लिए एक पंक्ति संख्या बनाना और अगली पंक्ति में शामिल होने और अगर LastUpdatedBy बदल गया है की तुलना। इस coalesce(C2.LastUpdatedBy, 0) से सावधान रहें। यह अंतिम पंक्ति प्राप्त करने के लिए है और 0 को कुछ पूर्णांक मान होने की आवश्यकता है जो LastUpdatedBy के रूप में उपयोग नहीं किया जाता है।

+0

हां! ऐसा लगता है कि चाल चल रही है! यह मुझे उचित डेटा दिया। उत्तर के रूप में चिह्नित। – Makotosan

+1

विश्वास नहीं कर सकता मैं इस तरह के एक साधारण समाधान से चूक गया, बस अपने शामिल खंड के साथ पिछले रिकॉर्ड की तुलना। धन्यवाद! – Makotosan

0

यह पूरी तरह अपरीक्षित है लेकिन यह एक काम कर समाधान का आधार बन सकता है:

SELECT 
    [Outer].[LastUpdatedOn], 
    [Outer].[LastUpdatedBy] 
FROM [HistoricalTable] AS [Outer] 
WHERE NOT EXISTS 
(
    SELECT * 
    FROM [HistoricalTable] AS [Middle] 
    WHERE [Middle].[LastUpdatedBy] = [Outer].[LastUpdatedBy] 
     AND [Middle].[LastUpdatedOn] > [Outer].[LastUpdatedOn] 
     AND [Middle].[LastUpdatedOn] <= ISNULL(
     (
      SELECT 
       MIN([Inner].[LastUpdatedOn]) 
      FROM [HistoricalTable] AS [Inner] 
      WHERE [Inner].[LastUpdatedBy] != [Outer].[LastUpdatedBy] 
       AND [Inner].[LastUpdatedOn] > [Outer].[LastUpdatedOn] 
     ), [Middle].[LastUpdatedOn]) 
) 

इस दृष्टिकोण से काम करता है यहां तक ​​कि अगर, प्रदर्शन शायद भयानक माना जाएगा कि आपके पास केवल कुछ मुट्ठी भर पंक्तियों से अधिक है।

तालिका में प्रत्येक पंक्ति के लिए यह सुनिश्चित करता है कि संदर्भ पंक्ति और सबसे पुरानी पंक्ति के बीच एक ही उपयोगकर्ता द्वारा किसी अन्य पंक्ति को मौजूद नहीं किया गया है जो एक अलग उपयोगकर्ता से जुड़ी संदर्भ पंक्ति से अधिक हालिया पंक्ति है।

2

सुनिश्चित नहीं है कि मुझे आपके प्रश्न में कुछ याद आ रहा है लेकिन क्या निम्न SQL समस्या का उत्तर नहीं देता है?

declare @HistoricalTable table (LastUpdatedOn datetime, LastUpdatedBy int); 

insert into @HistoricalTable (LastUpdatedOn, LastUpdatedBy) values 
('2011-06-07 13:07:26.917', 629),('2011-06-07 12:57:53.700', 629), 
('2011-06-07 12:57:44.387', 629),('2011-06-07 12:57:34.913', 629), 
('2011-06-07 12:57:25.040', 629),('2011-06-07 12:57:19.927', 629), 
('2011-06-07 12:55:17.460', 629),('2011-06-07 12:55:12.287', 629), 
('2011-06-07 12:30:34.377', 629),('2011-06-07 11:54:05.727', 4), 
('2011-06-07 11:50:02.723', 629),('2011-06-07 11:26:43.053', 629), 
('2011-06-07 10:54:32.867', 629),('2011-06-07 10:46:32.107', 629), 
('2011-06-07 10:40:52.937', 629),('2011-06-07 10:39:50.880', 3); 

select 
latest.* 
from 
(
select *, rank() over (partition by LastUpdatedBy order by LastUpdatedOn desc) as UpdateRank 
    from @HistoricalTable 
) latest 
where 
latest.UpdateRank = 1 
order by 
latest.LastUpdatedBy; 

LastUpdatedOn   LastUpdatedBy UpdateRank 
2011-06-07 10:39:50.880   3   1 
2011-06-07 11:54:05.727   4   1 
2011-06-07 13:07:26.917   629   1 
+0

काफी नहीं, चूंकि उपयोगकर्ता 629 के संपादन उपयोगकर्ता 4 के संपादन में बाधित थे, मेरे पास LastUpdatedBy = 629 – Makotosan

+0

के साथ 2 परिणाम होने चाहिए, वहां जाएं - आपके प्रश्न या परीक्षण डेटा या कुछ में कुछ याद किया होगा: पी लेकिन मुझे लगता है कि यह " हालांकि, मैं केवल उपयोगकर्ता द्वारा बनाए गए संपादनों की एक श्रृंखला के लिए नवीनतम रिकॉर्ड पुनर्प्राप्त करना चाहता हूं। " जिसने मुझे –

1

इसने मुझे आज सुबह मारा कि यह एक द्वीप समस्या है। यहाँ मेरी समाधान है:

CREATE TABLE #tmp (
LastUpdatedBy INT, 
LastUpdatedOn DATETIME 
) 

INSERT INTO #tmp 
     (LastUpdatedOn, LastUpdatedBy) 
VALUES ('2011-06-07 13:07:26.917', 629), 
     ('2011-06-07 12:57:53.700', 629), 
     ('2011-06-07 12:57:44.387', 629), 
     ('2011-06-07 12:57:34.913', 629), 
     ('2011-06-07 12:57:25.040', 629), 
     ('2011-06-07 12:57:19.927', 629), 
     ('2011-06-07 12:55:17.460', 629), 
     ('2011-06-07 12:55:12.287', 629), 
     ('2011-06-07 12:30:34.377', 629), 
     ('2011-06-07 11:54:05.727', 4), 
     ('2011-06-07 11:50:02.723', 629), 
     ('2011-06-07 11:26:43.053', 629), 
     ('2011-06-07 10:54:32.867', 629), 
     ('2011-06-07 10:46:32.107', 629), 
     ('2011-06-07 10:40:52.937', 629), 
     ('2011-06-07 10:39:50.880', 3) ; 

WITH cte 
      AS (SELECT [LastUpdatedOn], 
         [LastUpdatedBy], 
         ROW_NUMBER() OVER (PARTITION BY [LastUpdatedBy] ORDER BY [LastUpdatedOn] DESC) - ROW_NUMBER() OVER (ORDER BY [LastUpdatedOn] DESC) AS [Island] 
       FROM  #tmp 
      ), 
     cte2 
      AS (SELECT *, 
         ROW_NUMBER() OVER (PARTITION BY [Island] ORDER BY [LastUpdatedOn] DESC) AS [rn] 
       FROM  cte 
      ) 
    SELECT [LastUpdatedOn], 
      [LastUpdatedBy] 
    FROM cte2 
    WHERE [rn] = 1 
    ORDER BY [LastUpdatedOn] DESC ; 

"चाल" यहाँ ध्यान दें कि अगर आप दोनों एक विभाजन के भीतर और पूरे सेट के लिए ROW_NUMBER का ट्रैक रखने, दोनों के बीच अंतर जब विभाजन परिवर्तन बदल जाएगा।

+0

अच्छा समाधान भी फेंक दिया! सही आउटपुट देता है। +1 – Makotosan

संबंधित मुद्दे