क्या SQL सर्वर में कोई अधिकतम फ़ंक्शन है जो.NET में Math.Max जैसे दो मान लेता है?




sql-server (16)

अन्य उत्तरों अच्छे हैं, लेकिन यदि आपको नल मान रखने के बारे में चिंता करने की ज़रूरत है, तो आप इस संस्करण को चाह सकते हैं:

SELECT o.OrderId, 
   CASE WHEN ISNULL(o.NegotiatedPrice, o.SuggestedPrice) > ISNULL(o.SuggestedPrice, o.NegotiatedPrice)
        THEN ISNULL(o.NegotiatedPrice, o.SuggestedPrice)
        ELSE ISNULL(o.SuggestedPrice, o.NegotiatedPrice)
   END
FROM Order o

मैं इस तरह की एक प्रश्न लिखना चाहता हूं:

SELECT o.OrderId, MAX(o.NegotiatedPrice, o.SuggestedPrice)
FROM Order o

लेकिन यह नहीं है कि MAX फ़ंक्शन कैसे काम करता है, है ना? यह एक समग्र कार्य है इसलिए यह एक पैरामीटर की अपेक्षा करता है और फिर सभी पंक्तियों का MAX देता है।

क्या कोई जानता है कि इसे कैसे करना है?


अपने सबसे सरल रूप में ...

CREATE FUNCTION fnGreatestInt (@Int1 int, @Int2 int )
RETURNS int
AS
BEGIN

    IF @Int1 >= ISNULL(@Int2,@Int1)
        RETURN @Int1
    ELSE
        RETURN @Int2

    RETURN NULL --Never Hit

END

उप क्वेरी बाहरी क्वेरी से कॉलम तक पहुंच सकते हैं ताकि आप कॉलम में MAX जैसे योगों का उपयोग करने के लिए इस दृष्टिकोण का उपयोग कर सकें। (हालांकि अधिक उपयोगी कॉलम होने पर शायद अधिक उपयोगी)

;WITH [Order] AS
(
SELECT 1 AS OrderId, 100 AS NegotiatedPrice, 110 AS SuggestedPrice UNION ALL
SELECT 2 AS OrderId, 1000 AS NegotiatedPrice, 50 AS SuggestedPrice
)
SELECT
       o.OrderId, 
       (SELECT MAX(price)FROM 
           (SELECT o.NegotiatedPrice AS price 
            UNION ALL SELECT o.SuggestedPrice) d) 
        AS MaxPrice 
FROM  [Order]  o

एक पंक्ति में किया जा सकता है:

-- the following expression calculates ==> max(@val1, @val2)
SELECT 0.5 * ((@val1 + @val2) + ABS(@val1 - @val2)) 

संपादित करें: यदि आप बहुत बड़ी संख्या से निपट रहे हैं तो आपको एक पूर्णांक ओवरफ़्लो से बचने के लिए मूल्य चर को बड़े में परिवर्तित करना होगा।


एसक्यूएल सर्वर 2012 के लिए:

SELECT 
    o.OrderId, 
    IIF( o.NegotiatedPrice >= o.SuggestedPrice,
         o.NegotiatedPrice, 
         ISNULL(o.SuggestedPrice, o.NegiatedPrice) 
    )
FROM 
    Order o

ओह, मैंने अभी इस प्रश्न का एक डुप्पी पोस्ट किया है ...

जवाब यह है कि ओरेकल के ग्रेटेस्ट जैसे फ़ंक्शन में कोई भी अंतर्निहित नहीं है, लेकिन आप यूडीएफ के साथ 2 कॉलम के लिए एक समान परिणाम प्राप्त कर सकते हैं, नोट, sql_variant का उपयोग यहां काफी महत्वपूर्ण है।

create table #t (a int, b int) 

insert #t
select 1,2 union all 
select 3,4 union all
select 5,2

-- option 1 - A case statement
select case when a > b then a else b end
from #t

-- option 2 - A union statement 
select a from #t where a >= b 
union all 
select b from #t where b > a 

-- option 3 - A udf
create function dbo.GREATEST
( 
    @a as sql_variant,
    @b as sql_variant
)
returns sql_variant
begin   
    declare @max sql_variant 
    if @a is null or @b is null return null
    if @b > @a return @b  
    return @a 
end


select dbo.GREATEST(a,b)
from #t

kristof

यह उत्तर पोस्ट किया गया:

create table #t (id int IDENTITY(1,1), a int, b int)
insert #t
select 1,2 union all
select 3,4 union all
select 5,2

select id, max(val)
from #t
    unpivot (val for col in (a, b)) as unpvt
group by id

बड़ी संख्या के संबंध में ऊपर दिए गए उत्तर के लिए, आप अतिरिक्त / घटाव से पहले गुणा कर सकते हैं। यह थोड़ा बड़ा है लेकिन किसी भी कलाकार की आवश्यकता नहीं है। (मैं गति के लिए बात नहीं कर सकता लेकिन मुझे लगता है कि यह अभी भी बहुत तेज़ है)

0.5 * चुनें ((@ val1 + @ val2) + एबीएस (@ val1 - @ val2))

में परिवर्तन

चुनें @ val1 * 0.5 + @ val2 * 0.5 + एबीएस (@ val1 * 0.5 - @ val2 * 0.5)

यदि आप कास्टिंग से बचना चाहते हैं तो कम से कम एक विकल्प।


मुझे ऐसा नहीं लगता। मैं इसे दूसरे दिन चाहता था। मुझे सबसे करीब मिला था:

SELECT
  o.OrderId,
  CASE WHEN o.NegotiatedPrice > o.SuggestedPrice THEN o.NegotiatedPrice 
     ELSE o.SuggestedPrice
  END
FROM Order o

मैं शायद इसे इस तरह से नहीं करूँगा, क्योंकि यह पहले से उल्लिखित केस संरचनाओं से कम कुशल है - जब तक, शायद, आप दोनों प्रश्नों के लिए इंडेक्स को कवर नहीं करते थे। किसी भी तरह से, यह समान समस्याओं के लिए एक उपयोगी तकनीक है:

SELECT OrderId, MAX(Price) as Price FROM (
   SELECT o.OrderId, o.NegotiatedPrice as Price FROM Order o
   UNION ALL
   SELECT o.OrderId, o.SuggestedPrice as Price FROM Order o
) as A
GROUP BY OrderId

यदि आप SQL Server 2008 (या ऊपर) का उपयोग कर रहे हैं, तो यह बेहतर समाधान है:

SELECT o.OrderId,
       (SELECT MAX(Price)
        FROM (VALUES (o.NegotiatedPrice),(o.SuggestedPrice)) AS AllPrices(Price))
FROM Order o

सभी क्रेडिट और वोटों को संबंधित प्रश्न के उत्तर में स्वेन के जवाब में जाना चाहिए , "एकाधिक कॉलम का एसक्यूएल MAX?"
मैं कहता हूं कि यह " सर्वश्रेष्ठ जवाब " है क्योंकि:

  1. इसके लिए यूनियन, PIVOT, UNPIVOT, UDF, और पागल-लंबे केस स्टेटमेंट्स के साथ आपके कोड को जटिल करने की आवश्यकता नहीं है।
  2. यह नल को संभालने की समस्या से पीड़ित नहीं है, यह उन्हें ठीक से संभालता है।
  3. "MIN", "AVG", या "SUM" के साथ "MAX" को स्वैप करना आसान है। आप कई अलग-अलग स्तंभों पर कुल मिलाकर किसी भी समग्र फ़ंक्शन का उपयोग कर सकते हैं।
  4. आप मेरे द्वारा उपयोग किए जाने वाले नामों तक सीमित नहीं हैं (यानी "ऑलप्रिसेस" और "मूल्य")। अगले व्यक्ति के लिए इसे पढ़ने और समझना आसान बनाने के लिए आप अपना नाम चुन सकते हैं।
  5. आप SQL सर्वर 2008 के derived_tables का उपयोग करके एकाधिक समेकित पा सकते हैं:
    MAX (ए), MAX (बी) से चुनें (मूल्य (1, 2), (3, 4), (5, 6), (7, 8), (9, 10)) माईटेबल (ए, बी)

यह उतना आसान है जितना:

CREATE FUNCTION InlineMax
(
    @p1 sql_variant,
    @p2 sql_variant
)  RETURNS sql_variant
AS
BEGIN
    RETURN CASE 
        WHEN @p1 IS NULL AND @p2 IS NOT NULL THEN @p2 
        WHEN @p2 IS NULL AND @p1 IS NOT NULL THEN @p1
        WHEN @p1 > @p2 THEN @p1
        ELSE @p2 END
END;

यहां एक केस उदाहरण दिया गया है जो नल को संभालना चाहिए और एमएसएसक्यूएल के पुराने संस्करणों के साथ काम करेगा। यह लोकप्रिय उदाहरणों में से एक में इनलाइन फ़ंक्शन पर आधारित है:

case
  when a >= b then a
  else isnull(b,a)
end

सरल नल हैंडलिंग के साथ @ सॉट लैंगहम का जवाब यहां दिया गया है:

SELECT
      o.OrderId,
      CASE WHEN (o.NegotiatedPrice > o.SuggestedPrice OR o.SuggestedPrice IS NULL) 
         THEN o.NegotiatedPrice 
         ELSE o.SuggestedPrice
      END As MaxPrice
FROM Order o

IIF फ़ंक्शन का प्रयास क्यों न करें (SQL Server 2012 और बाद में आवश्यक है)

IIF(a>b, a, b)

बस।


CREATE FUNCTION [dbo].[fnMax] (@p1 INT, @p2 INT)
RETURNS INT
AS BEGIN

    DECLARE @Result INT

    SET @p2 = COALESCE(@p2, @p1)

    SELECT
        @Result = (
                   SELECT
                    CASE WHEN @p1 > @p2 THEN @p1
                         ELSE @p2
                    END
                  )

    RETURN @Result

END

DECLARE @MAX INT
@MAX = (SELECT MAX(VALUE) 
               FROM (SELECT 1 AS VALUE UNION 
                     SELECT 2 AS VALUE) AS T1)







max