SQL

2011-06-01 13 views
23

में प्रति समूह अंतिम रिकॉर्ड कैसे प्राप्त करें मुझे एक दिलचस्प समस्या का सामना करना पड़ रहा है। मेरे पास निम्न संरचना वाला एक टेबल है:SQL

CREATE TABLE [dbo].[Event] 
(
    Id int IDENTITY(1,1) NOT NULL, 
    ApplicationId nvarchar(32) NOT NULL, 
    Name nvarchar(128) NOT NULL, 
    Description nvarchar(256) NULL, 
    Date nvarchar(16) NOT NULL, 
    Time nvarchar(16) NOT NULL, 
    EventType nvarchar(16) NOT NULL, 
    CONSTRAINT Event_PK PRIMARY KEY CLUSTERED (Id) WITH (
     PAD_INDEX = OFF, 
     STATISTICS_NORECOMPUTE = OFF, 
     IGNORE_DUP_KEY = OFF, 
     ALLOW_ROW_LOCKS = ON, 
     ALLOW_PAGE_LOCKS = ON 
    ) 
) 

तो मुद्दा यह है कि मुझे यह डेटा ग्रिड में प्रदर्शित करना है। दो आवश्यकताएं हैं। सबसे पहले सभी घटनाओं को प्रदर्शित करना है चाहे उन्हें किस एप्लिकेशन ने फेंक दिया हो। यह आसान है - एक चयन कथन बहुत आसानी से काम करेगा।

दूसरी आवश्यकता Application द्वारा घटनाओं को समूहबद्ध करने में सक्षम होना है। दूसरे शब्दों में सभी घटनाओं को इस तरह प्रदर्शित करें कि यदि ApplicationId एक से अधिक बार दोहराया जाता है, तो प्रत्येक एप्लिकेशन के लिए केवल अंतिम प्रविष्टि लें। इस बिंदु पर ईवेंट (आईडी) की प्राथमिक कुंजी अब इस क्वेरी/दृश्य में आवश्यक नहीं है।

आप यह भी नोटिस कर सकते हैं कि ईवेंट दिनांक और समय स्ट्रिंग प्रारूप में हैं। यह ठीक है क्योंकि वे मानक दिनांक समय प्रारूपों का पालन करते हैं: मिमी/डीडी/yyyy और एचएच: मिमी: एसएस। मैं उन के रूप में निम्नानुसार खींच कर सकते हैं:

Convert(DateTime, (Date + ' ' + Time)) AS 'TimeStamp' 

मेरे मुद्दा यह है कि अगर मैं शेष कॉलम पर समग्र कार्यों का उपयोग मैं नहीं जानता कि उनका व्यवहार होता है:

SELECT 
    ApplicationId, 
    MAX(Name), 
    MAX(Description), 
    MAX(CONVERT(DateTime, (Date + ' ' + Time))) AS 'TimeStamp', 
    MAX(EventType) 
FROM 
    Event 
GROUP BY 
    ApplicationId 

कारण मैं कर रहा हूँ ऐसा करने में संकोच करना इसलिए है क्योंकि MAX जैसे फ़ंक्शन रिकॉर्ड के एक (उप) सेट से दिए गए कॉलम के लिए सबसे बड़ा मान वापस कर देगा। यह आवश्यक रिकॉर्ड खींचने के लिए आवश्यक नहीं है!

प्रति आवेदन आधार पर केवल अंतिम रिकॉर्ड का चयन करने के तरीके पर कोई विचार?

+2

विंडोिंग फ़ंक्शन का उपयोग करें (ओरेकल में, इसलिए row_number() से अधिक (विभाजन द्वारा ...), AFAIK SQL सर्वर की समान कार्यक्षमता है। –

उत्तर

40

आप ranking function और common table expression का उपयोग कर सकते हैं।

WITH e AS 
(
    SELECT *, 
     ROW_NUMBER() OVER 
     (
      PARTITION BY ApplicationId 
      ORDER BY CONVERT(datetime, [Date], 101) DESC, [Time] DESC 
     ) AS Recency 
    FROM [Event] 
) 
SELECT * 
FROM e 
WHERE Recency = 1 
+0

आप दिनांक और समय के अनुसार किसी डेटाटाइम मान में परिवर्तित किए बिना ऑर्डर नहीं कर सकते हैं, क्योंकि 'mm/dd/yyyy' प्रारूप स्ट्रिंग के रूप में सही ढंग से सॉर्ट नहीं करता है। –

+1

धन्यवाद @ एंथनी फुल। यह काम करता है हालांकि मुझे समझ में नहीं आता कि कैसे। – bleepzter

+0

@damien अच्छा पकड़ो। मैंने यूएस दिनांक (महीने-दिन-वर्ष) को क्रमबद्ध तिथियों में परिवर्तित करने के लिए ऑर्डर द्वारा ऑर्डर किया है। –

0
SELECT 
    E.ApplicationId, 
    E.Name, 
    E.Description, 
    CONVERT(DateTime, (E.Date + ' ' + E.Time)) AS 'TimeStamp', 
    E.EventType 
FROM 
    Event E 
    JOIN (SELECT ApplicationId, 
       MAX(CONVERT(DateTime, (Date + ' ' + Time))) AS max_date 
      FROM Event 
     GROUP BY ApplicationId) EM 
     on EM.ApplicationId = E.ApplicationId 
    and EM.max_date = CONVERT(DateTime, (E.Date + ' ' + E.Time))) 
0

क्योंकि तुम वहाँ में एक जहां खंड नहीं है, अभिलेखों का सबसेट, सभी रिकॉर्ड है। लेकिन आप मुझे लगता है कि गलत कॉलम पर अधिकतम डाल रहे हैं। यह क्वेरी आपको वह देगी जो आप खोज रहे हैं।

Select max(applicationid), name, description, CONVERT(DateTime, (Date + ' ' + Time)) 
from event 
group by name, description, CONVERT(DateTime, (Date + ' ' + Time)) 
0

आप यह करने के लिए एक subqery या CTE तालिका का उपयोग कर सकते हैं:

;WITH CTE_LatestEvents as (
SELECT 
    ApplicationId,  
    MAX(CONVERT(DateTime, (Date + ' ' + Time))) AS 'LatestTimeStamp', 
FROM 
    Event 
GROUP BY 
    ApplicationId 
) 
SELECT 
    ApplicationId, 
    Name, 
    Description, 
    CONVERT(DateTime, (Date + ' ' + Time))) AS 'TimeStamp', 
    EventType 
FROM 
    Event e 
    Join CTE_LatestEvents le 
     on e.applicationid = le.applicationid 
     and CONVERT(DateTime, (e.Date + ' ' + e.Time))) = le.LatestTimeStamp 
0

आप द्वारा समूह के साथ एक उप क्वेरी का उपयोग कर सकते हैं - तर्क से समूह का चयन में होने की जरूरत नहीं है। यह मानता है कि आईडी एक ऑटो वृद्धि हुई है ताकि सबसे बड़ा सबसे हालिया है।

SELECT 
    ApplicationId, 
    Name, 
    Description, 
    CONVERT(DateTime, (Date + ' ' + Time)) AS 'TimeStamp', 
    EventType 
FROM 
    Event e 
WHERE 
    Id in (select max(Id) from Event GROUP BY ApplicationId) 
0

मुझे लगता है कि वहाँ पिछले डाला रिकॉर्ड लाने के लिए तैयार बाहर कई के लिए काम करेंगे और इसके द्वारा समूह होना चाहिए:

चयन * से (चयन * द्वारा आईडी DESC TableName आदेश से) एक्स ग्रुप के रूप में FieldName

द्वारा

यह निम्न के लिए काम करेंगे:

तालिका संरचना आईडी नाम स्थिति 1 जुनैद हाँ 2 जवाद नहीं 3 फहद हाँ 4 जुनैद नहीं 5 काशिफ हाँ

बाद क्वेरी से ऊपर आईडी नाम स्थिति परिणाम 4 जुनैद नहीं 2 जवाद नहीं 3 फहद हाँ 4 काशिफ हाँ

यह केवल नामों के समूह के अंतिम रिकॉर्ड के परिणामस्वरूप होता है।

6

के बाद से SQL सर्वर 2012 आप कर सकते हैं बस

SELECT 
    [Month] 
    , [First] = FIRST_VALUE(SUM([Clicks])) OVER (ORDER BY [Month]) 
    , [Last] = FIRST_VALUE(SUM([Clicks])) OVER (ORDER BY [Month] DESC) 
FROM 
    [dbo].[Table] 
GROUP BY [Month] 
ORDER BY [Month] 
+2

बेशक वहाँ LAST_VALUE भी है – sehe

0

6 साल एसक्यूएल सर्वर के लिए एक और जवाब के बाद:

select t1.[Id], t2.[Value] 
from [dbo].[Table] t1 
    outer apply ( 
    select top 1 [Value] 
     from [dbo].[Table] t2 
     where t2.[Month]=t1.[Month] 
     order by [dbo].[Date] desc 
) 

हालांकि मैं सुविधा पर अपनी विशिष्ट साथ ज्यादा बेहतर Postgresql समाधान चाहते हैं जो अच्छे है टाइप करने के लिए और अधिक कुशल:

select distinct on (id),val 
from tbl 
order by id,val 

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