sql - कई कॉलम से अंतिम तिथियां प्राप्त करें
sql-server datetime (4)
ऐसा लगता है कि यह एक आसान होना चाहिए। मुझे नवीनतम तिथियां कैसे मिलती हैं जो विभिन्न कॉलमों में हैं
DROP TABLE #indebtedness
CREATE TABLE #indebtedness (call_case CHAR(10), date1 DATETIME, date2 DATETIME, date3 DATETIME)
INSERT #indebtedness VALUES ('Key1', '2019-10-30', '2019-11-30', '2019-10-25')
INSERT #indebtedness VALUES ('Key2', '2019-10-20', '2019-10-30', '2019-10-15')
INSERT #indebtedness VALUES ('Key3', '2019-11-11', '2019-10-29', '2019-10-30')
INSERT #indebtedness VALUES ('Key4', null , '2019-10-29', '2019-10-13')
select call_case, ?? AS 'Latest Date' from #indebtedness
मैं चाहूंगा कि परिणाम:
call_case Latest Date
Key1 2019-11-30
Key2 2019-10-30
Key3 2019-11-11
Key4 2019-10-29
इसे इस्तेमाल करे:
SELECT call_case,
(SELECT
MAX(call_case)
FROM ( VALUES
(MAX(date1)),
(MAX(date2))
,(max(date3))
) MyAlias(call_case)
)
FROM #indebtedness
group by call_case
एक
CASE
अभिव्यक्ति का उपयोग करें:
SELECT
call_case,
CASE WHEN date1 > date2 AND date1 > date3
THEN date1
WHEN date2 > date3
THEN date2
ELSE date3 END AS [Latest Date]
FROM #indebtedness;
डेमो
ध्यान दें कि कुछ डेटाबेस, जैसे कि MySQL, SQL सर्वर और SQLite, एक स्केलर सबसे बड़े फ़ंक्शन का समर्थन करते हैं।
SQL सर्वर नहीं करता है, इसलिए हम एक
CASE
अभिव्यक्ति का उपयोग वर्कअराउंड के रूप में कर सकते हैं।
संपादित करें:
ऐसा प्रतीत होता है कि आपकी वास्तविक तालिका में, तीन या अधिक स्तंभों में से एक में
NULL
मान हो सकते हैं।
हम उपरोक्त क्वेरी को निम्नानुसार अनुकूलित कर सकते हैं:
SELECT
call_case,
CASE WHEN (date1 > date2 OR date2 IS NULL) AND (date1 > date3 OR date3 IS NULL)
THEN date1
WHEN date2 > date3 OR date3 IS NULL
THEN date2
ELSE date3 END AS [Latest Date]
FROM #indebtedness;
डेमो
वर्तमान में स्वीकृत उत्तर सबसे अच्छा उत्तर है, लेकिन मुझे नहीं लगता कि यह समझाने का एक अच्छा पर्याप्त काम करता है कि क्यों। अन्य उत्तर निश्चित रूप से एक नज़र में बहुत साफ दिखते हैं (जो उस बदसूरत मामले के बयान को लिखना चाहते हैं), लेकिन जब आप पैमाने पर काम करना शुरू करते हैं तो बहुत खराब होने की संभावना होती है।
SELECT @@VERSION
Microsoft SQL Server 2016 (SP2) (KB4052908) - 13.0.5026.0 (X64)
Mar 18 2018 09:11:49
Copyright (c) Microsoft Corporation
Developer Edition (64-bit) on Windows 10 Enterprise 10.0 <X64> (Build 17763: )
यहाँ है कि मैं सब कुछ कैसे सेट करता हूं
DECLARE @Offset bigint = 0;
DECLARE @Max bigint = 10000000;
DROP TABLE IF EXISTS #Indebtedness;
CREATE TABLE #Indebtedness
(
call_case char(10) COLLATE DATABASE_DEFAULT NOT NULL,
date1 datetime NULL,
date2 datetime NULL,
date3 datetime NULL
);
WHILE @Offset < @Max
BEGIN
INSERT INTO #Indebtedness
( call_case, date1, date2, date3 )
SELECT @Offset + ROW_NUMBER() OVER ( ORDER BY ( SELECT NULL )),
DATEADD( DAY,
CASE WHEN RAND() > 0 THEN 1
ELSE -1 END * ROUND( RAND(), 0 ),
CURRENT_TIMESTAMP ),
DATEADD( DAY,
CASE WHEN RAND() > 0 THEN 1
ELSE -1 END * ROUND( RAND(), 0 ),
CURRENT_TIMESTAMP ),
DATEADD( DAY,
CASE WHEN RAND() > 0 THEN 1
ELSE -1 END * ROUND( RAND(), 0 ),
CURRENT_TIMESTAMP )
FROM master.dbo.spt_values a
CROSS APPLY master.dbo.spt_values b;
SET @Offset = @Offset + ROWCOUNT_BIG();
END;
मेरे सिस्टम पर यह मुझे तालिका में 12,872,738 पंक्तियों में मिलती है।
यदि मैं उपरोक्त प्रत्येक प्रश्न (
SELECT INTO
जाता हूं तो मुझे SSMS में परिणाम प्रिंट करने के लिए प्रतीक्षा करने की आवश्यकता नहीं है) की कोशिश करता हूं, मुझे निम्न परिणाम मिलते हैं:
Method | CPU time (ms) | Elapsed time (ms) | Relative Cost
-----------------------------------------------------------------------------------------
Tim Biegeleisen (CASE) | 13485 | 2167 | 2%
Red Devil (Subquery over MAX columns) | 55187 | 9891 | 14%
Vignesh Kumar (Subquery over columns) | 33750 | 5139 | 5%
Serkan Arslan (UNPIVOT) | 86205 | 15023 | 12%
Metal (STRING_SPLIT) | 459668 | 186742 | 68%
यदि आप क्वेरी योजनाओं को देखते हैं, तो यह बहुत स्पष्ट हो जाता है कि क्यों - किसी भी प्रकार की अनप्राइवेट या एग्रीगेट (या स्वर्ग
STRING_SPLIT
) को
STRING_SPLIT
आप उन सभी अतिरिक्त ऑपरेटरों के साथ समाप्त हो जाएंगे
STRING_SPLIT
आपको आवश्यकता नहीं है (और यह योजना को बल देता है। समानांतर में जाना, संसाधनों को दूर ले जाना अन्य प्रश्न चाहते हो सकता है)।
अनुबंध से,
CASE
आधारित समाधान समानांतर नहीं चलता है, बहुत जल्दी चलता है, और अविश्वसनीय रूप से सरल है।
इस मामले में, जब तक आपके पास असीमित संसाधन (आप नहीं हैं), आपको सबसे सरल और सबसे तेज़ दृष्टिकोण चुनना चाहिए।
यदि आपको नए कॉलम जोड़ने और केस स्टेटमेंट का विस्तार करने की आवश्यकता है तो क्या करना है, इस पर सवाल था। हाँ, यह कमज़ोर हो जाता है, लेकिन ऐसा हर दूसरे उपाय से होता है। यदि यह वास्तव में एक प्रशंसनीय वर्कफ़्लो है, तो आपको अपनी तालिका को फिर से डिज़ाइन करना चाहिए। आप जो चाहते हैं वह कुछ इस तरह दिखता है:
CREATE TABLE #Indebtedness2
(
call_case char(10) COLLATE DATABASE_DEFAULT NOT NULL,
activity_type bigint NOT NULL, -- This indicates which date# column it was, if you care
timestamp datetime NOT NULL
);
SELECT Indebtedness.call_case,
Indebtedness.activity_type,
Indebtedness.timestamp
FROM ( SELECT call_case,
activity_type,
timestamp,
ROW_NUMBER() OVER ( PARTITION BY call_case
ORDER BY timestamp DESC ) RowNumber
FROM #Indebtedness2 ) Indebtedness
WHERE Indebtedness.RowNumber = 1;
यह निश्चित रूप से संभावित प्रदर्शन के मुद्दों से मुक्त नहीं है, और इसके लिए सावधान इंडेक्स ट्यूनिंग की आवश्यकता होगी, लेकिन संभावित बेस्टस्टैम्प की एक मनमानी संख्या को संभालने का सबसे अच्छा तरीका है
यदि कोई उत्तर हटा दिया जाता है, तो यहां वे संस्करण हैं जिनकी मैं तुलना कर रहा था (क्रम में)
SELECT
call_case,
CASE WHEN date1 > date2 AND date1 > date3
THEN date1
WHEN date2 > date3
THEN date2
ELSE date3 END AS [Latest Date]
FROM #indebtedness;
SELECT call_case,
(SELECT Max(v)
FROM (VALUES (date1), (date2), (date3),...) AS value(v)) as [MostRecentDate]
FROM #indebtedness
SELECT call_case,
(SELECT
MAX(call_case)
FROM ( VALUES
(MAX(date1)),
(MAX(date2))
,(max(date3))
) MyAlias(call_case)
)
FROM #indebtedness
group by call_case
select call_case, MAX(date) [Latest Date] from #indebtedness
UNPIVOT(date FOR col IN ([date1], [date2], [date3])) UNPVT
GROUP BY call_case
select call_case , max(cast(x.Item as date)) as 'Latest Date' from #indebtedness t
cross apply dbo.SplitString(concat(date1, ',', date2, ',', date3), ',') x
group by call_case
MAX()
उपयोग करें
SELECT call_case,
(SELECT Max(v)
FROM (VALUES (date1), (date2), (date3),...) AS value(v)) as [MostRecentDate]
FROM #indebtedness
CASE
उपयोग करें
SELECT
CASE
WHEN Date1 >= Date2 AND Date1 >= Date3 THEN Date1
WHEN Date2 >= Date1 AND Date2 >= Date3 THEN Date2
WHEN Date3 >= Date1 AND Date3 >= Date2 THEN Date3
ELSE Date1
END AS MostRecentDate
FROM #indebtedness