SQL में न्यूनतम दो मान प्राप्त करना


180

मेरे पास दो चर हैं, एक को बुलाया जाता है PaidThisMonth, और दूसरे को बुलाया जाता है OwedPast। वे दोनों SQL में कुछ उपश्रेणियों के परिणाम हैं। मैं दोनों में से छोटे का चयन कैसे कर सकता हूं और इसे शीर्षक मान के रूप में वापस कर सकता हूं PaidForPast?

MINसमारोह कॉलम, नहीं चर पर काम करता है।


1
यदि आप Postgres या MySQL पर हैं, तो @ Gil_Margolin के उत्तर पर जाएं।
नौमेनन

जवाबों:


127

उदाहरण:

   Select Case When @PaidThisMonth < @OwedPast 
               Then @PaidThisMonth Else @OwedPast End PaidForPast

इनलाइन तालिका के रूप में मूल्यवान यूडीएफ

CREATE FUNCTION Minimum
(@Param1 Integer, @Param2 Integer)
Returns Table As
Return(Select Case When @Param1 < @Param2 
                   Then @Param1 Else @Param2 End MinValue)

उपयोग:

Select MinValue as PaidforPast 
From dbo.Minimum(@PaidThisMonth, @OwedPast)

ADDENDUM: केवल दो संभावित मूल्यों को संबोधित करते समय यह सबसे अच्छा है, यदि दो से अधिक हैं, तो Values ​​खंड का उपयोग करके क्रेग के उत्तर पर विचार करें ।


बेहतर समझने योग्य वाक्य रचना: वापसी (minValue = केस का चयन करें जब @@ param1 <@@ param2 फिर @@ param1 वरना @@ param2 अंत)। ठीक है, यह सामान्य नहीं किया जा सकता है, मुझे नहीं पता। लेकिन यह बहुत अधिक समझने योग्य है और इसे सामान्य किया जाना चाहिए।
सॉफ्टलिंय

1
@ क्रेग का जवाब पसंद करने का एक और कारण शून्य से निपटने के कारण है। मूल्यों तुलना की जा रही नल हैं, और अगर एक मूल्यों की तुलना की जा रही, जब परीक्षण के आदेश पर निर्भर करता है (जब तक आप IsNull के उपयोग को जोड़ने) अशक्त, स्विच मामले से पता चला हो सकता है वापसी अशक्त या मूल्य है। क्रेग का दृष्टिकोण हमेशा नॉट-नल मूल्य के चयन को पसंद करेगा जो मुझे अधिक सही लगता है, कम से कम मेरे वर्तमान उपयोग-मामले में अशक्त तिथियों की तुलना में।
निज

148

SQL सर्वर 2012 और 2014 IIF (प्रतियोगिता, सत्य, असत्य) फ़ंक्शन का समर्थन करता है। इस प्रकार न्यूनतम चयन के लिए आप इसका उपयोग कर सकते हैं

SELECT IIF(first>second, second, first) the_minimal FROM table

जबकि IIF लिखने के लिए सिर्फ एक शॉर्टहैंड है CASE...WHEN...ELSE, यह लिखना आसान है।


8
IIFके लिए सिर्फ एक कृत्रिम चीनी है CASE...WHEN...ELSE
सलमान ए

55
संभवतः हाँ। लेकिन लिखना आसान है।
मर्ट गुल्सोइ

1
@ MertGülsoy और पढ़ने में आसान है, जो सही होने के बाद सभी की प्राथमिकता सूची में सबसे ऊपर होना चाहिए।
डैनियल

119

CASE, IIF, और UDF का उपयोग करने वाले समाधान पर्याप्त हैं, लेकिन 2 तुलनात्मक मूल्यों का उपयोग करके सामान्य मामले में समस्या का विस्तार करते समय अव्यवहारिक है। SQL Server 2008 में सामान्यीकृत समाधान VALUES खंड के एक अजीब अनुप्रयोग का उपयोग करता है:

SELECT
PaidForPast=(SELECT MIN(x) FROM (VALUES (PaidThisMonth),(OwedPast)) AS value(x))

इस वेबसाइट के कारण क्रेडिट: http://sqlblog.com/blogs/jamie_thomson/archive/2012/01/20/use-values-clause-to-get-the-maximum-value-from-nome-columns-sql- सर्वर-टी sql.aspx


12
यह सबसे अच्छा जवाब है
FindOutIslamNow

यदि आप शून्य गैर शून्य चाहते हैं:MIN(x*(case x when 0 then null else 1 end))
mpag

मार्टिन ने सिवाय चार साल पहले एक ही जवाब दिया था, और वास्तव में इसे दो से अधिक मूल्यों के साथ दिखाया ...
Auspex

4
एसेक्स, मार्टिनसी का उत्तर असंबंधित है। यह उत्तर यूनियनों का उपयोग नहीं करता है।
क्रेग

30

मेरे पास बस एक स्थिति थी जहां मुझे एक अद्यतन के भीतर अधिकतम 4 जटिल चयन खोजने थे। इस दृष्टिकोण के साथ आप जितने चाहें उतने हो सकते हैं!

आप एडिशनल सेलेक्ट्स के साथ नंबर भी बदल सकते हैं

select max(x)
 from (
 select 1 as 'x' union
 select 4 as 'x' union
 select 3 as 'x' union
 select 2 as 'x' 
 ) a

अधिक जटिल उपयोग

 @answer = select Max(x)
           from (
                select @NumberA as 'x' union
                select @NumberB as 'x' union
                select @NumberC as 'x' union
                select (
                       Select Max(score) from TopScores
                       ) as 'x' 
     ) a

मुझे यकीन है कि एक यूडीएफ में बेहतर प्रदर्शन होगा।


मुझे यह पसंद है कि एक के बाद से यह मूल एसक्यूएल है। इसके अलावा, यूडीएफ तेजी से जरूरी नहीं हैं। अधिकांश कॉलम स्टोरों के लिए, प्रत्येक विशेषता (मेरा मानना ​​है कि आप विशेषताओं पर फ़िल्टर करने के लिए भी जा रहे हैं) की गणना समानांतर में की जा सकती है और बस योग्यता सेट को संघबद्ध किया जाता है। इसलिए यूनियनें प्रति से धीमी नहीं हैं।
बाउंसर

सरल और भयानक।
ashleedawg

22

MySQL या PostgreSQL 9.3+ के लिए, एक बेहतर तरीका यह है कि कार्यों LEASTऔर GREATESTकार्यों का उपयोग करें ।

SELECT GREATEST(A.date0, B.date0) AS date0, 
       LEAST(A.date1, B.date1, B.date2) AS date1
FROM A, B
WHERE B.x = A.x

साथ में:

  • GREATEST(value [, ...]): प्रदान किए गए मूल्यों से सबसे बड़ा (अधिकतम-मूल्यवान) तर्क लौटाता है
  • LEAST(value [, ...])रिटर्न छोटी से छोटी मूल्यों से (न्यूनतम मूल्य) तर्क प्रदान की

दस्तावेज़ीकरण लिंक:


यह भी PostgreSQL में काम करता है (और यह वास्तव में मैं क्या देख रहा था :) देखें: Postgresql.org/docs/9.5/static/functions-conditional.html
अल्बर्ट वेका सिंटोरा

1
यह अब तक का सबसे अच्छा जवाब है।
रॉबर्टो रोड्रिग्ज

2
@RobertoRodriguez यह सबसे अच्छा होगा यदि प्रश्न में MySQL या PostgreSQL को प्रश्न के भाग के रूप में टैग किया गया हो। सवाल विशेष रूप से tsql के बारे में था इसलिए यह उत्तर बिल्कुल भी मदद नहीं करता है।
जम्मौरियर

यह MSSQL के लिए जवाब नहीं है
मुजाहिस्क

13

यहाँ एक चाल है यदि आप अधिकतम गणना करना चाहते हैं (क्षेत्र, 0):

SELECT (ABS(field) + field)/2 FROM Table

रिटर्न 0 यदि fieldऋणात्मक है, और, वापसी field


3
तो, न्यूनतम (@a, @ बी) की गणना करने के लिए, आप उपयोग कर सकते हैं:SELECT @a - ( ABS(@a-@b) + (@a-@b) ) / 2
scottyc

1
और प्रकार अतिप्रवाह के बारे में मत भूलना;)
pkuderov

क्या यह फ्लोटिंग-पॉइंट सटीक दृष्टिकोण से बचा है? क्या यह निश्चित है, कि परिणाम शून्य के करीब कभी नहीं होगा लेकिन नकारात्मक होगा?
ज्यूरफ

6

CASE स्टेटमेंट का उपयोग करें।

उदाहरण बी इस पृष्ठ में वह होना चाहिए जो आप करने की कोशिश कर रहे हैं:
http://msdn.microsoft.com/en-us/library/ms181765.aspx

यहाँ पृष्ठ से कोड है:

USE AdventureWorks;
GO
SELECT   ProductNumber, Name, 'Price Range' = 
      CASE 
         WHEN ListPrice =  0 THEN 'Mfg item - not for resale'
         WHEN ListPrice < 50 THEN 'Under $50'
         WHEN ListPrice >= 50 and ListPrice < 250 THEN 'Under $250'
         WHEN ListPrice >= 250 and ListPrice < 1000 THEN 'Under $1000'
         ELSE 'Over $1000'
      END
FROM Production.Product
ORDER BY ProductNumber ;
GO

2

मानों की श्रेणी सम्मिलित करने के लिए एक अस्थायी तालिका का उपयोग करें, फिर संग्रहीत कार्यविधि या UDF के भीतर से अस्थायी तालिका के न्यूनतम / अधिकतम का चयन करें। यह एक बुनियादी निर्माण है, इसलिए आवश्यकतानुसार स्वतंत्र महसूस करें।

उदाहरण के लिए:

CREATE PROCEDURE GetMinSpeed() AS
BEGIN

    CREATE TABLE #speed (Driver NVARCHAR(10), SPEED INT);
    '
    ' Insert any number of data you need to sort and pull from
    '
    INSERT INTO #speed (N'Petty', 165)
    INSERT INTO #speed (N'Earnhardt', 172)
    INSERT INTO #speed (N'Patrick', 174)

    SELECT MIN(SPEED) FROM #speed

    DROP TABLE #speed

END

2

यह 5 तारीख तक काम करता है और नल को संभालता है। बस इसे इनलाइन फ़ंक्शन के रूप में काम करने के लिए नहीं मिला।

CREATE FUNCTION dbo.MinDate(@Date1 datetime = Null,
                            @Date2 datetime = Null,
                            @Date3 datetime = Null,
                            @Date4 datetime = Null,
                            @Date5 datetime = Null)
RETURNS Datetime AS
BEGIN
--USAGE select dbo.MinDate('20120405',null,null,'20110305',null)
DECLARE @Output datetime;

WITH Datelist_CTE(DT)
AS (
        SELECT @Date1 AS DT WHERE @Date1 is not NULL UNION
        SELECT @Date2 AS DT WHERE @Date2 is not NULL UNION
        SELECT @Date3 AS DT WHERE @Date3 is not NULL UNION
        SELECT @Date4 AS DT WHERE @Date4 is not NULL UNION
        SELECT @Date5 AS DT WHERE @Date5 is not NULL
   )
Select @Output=Min(DT) FROM Datelist_CTE

RETURN @Output
END

बस एहसास हुआ कि आपको मीनार की जरूरत नहीं है क्योंकि MIN वैसे भी नल को हटा देगा।
लॉरेंस

2

मैथमैटिक्स और स्कॉटी से शानदार तर्क / कोड पर बिल्डिंग, मैं प्रस्तुत करता हूं:

DECLARE @a INT, @b INT, @c INT = 0

WHILE @c < 100
    BEGIN
        SET @c += 1
        SET @a = ROUND(RAND()*100,0)-50
        SET @b = ROUND(RAND()*100,0)-50
        SELECT @a AS a, @b AS b,
            @a - ( ABS(@a-@b) + (@a-@b) ) / 2 AS MINab,
            @a + ( ABS(@b-@a) + (@b-@a) ) / 2 AS MAXab,
            CASE WHEN (@a <= @b AND @a = @a - ( ABS(@a-@b) + (@a-@b) ) / 2)
            OR (@a >= @b AND @a = @a + ( ABS(@b-@a) + (@b-@a) ) / 2)
            THEN 'Success' ELSE 'Failure' END AS Status
    END

हालाँकि, स्कॉट फंक्शन में स्कॉट फंक्शन से कूदना मेरे लिए स्पष्ट होना चाहिए था, यह नहीं था, इसलिए मैंने इसके लिए हल किया है और इसे यहां शामिल किया है: SELECT @a + (ABS (@ b- @ @ a) + ( @ b- @ a)) / 2. यादृच्छिक रूप से उत्पन्न संख्याएँ, जबकि प्रमाण नहीं, कम से कम संदेह व्यक्त करना चाहिए कि दोनों सूत्र सही हैं।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.