CEILING का उपयोग करते समय CASE अभिव्यक्ति गलत मान देती है


11

मैं एक ऐसे मुद्दे पर भाग गया हूं जहां एक CASEअभिव्यक्ति वापस नहीं आती है जो मैं उम्मीद करता हूं।

एक परीक्षण के रूप में, मैंने एक दशमलव चर जोड़ा और उसी CASEअभिव्यक्ति को उसके खिलाफ चलाया और यह ठीक काम करता है, परिणामों की वापसी करते हुए जैसा कि मैं उम्मीद करता हूं (जब मूल्य बढ़ IsGun=1रहा है। लेकिन जब मैं उसी CASEअभिव्यक्ति को किसी अन्य दशमलव मान के खिलाफ चलाता हूं , तो यह हमेशा लौटता है। CEILING()फ़ंक्शन के साथ मान और मूल मूल्य कभी नहीं लौटाता है।

यहाँ SQL कोड है:

DECLARE @Num decimal(8,2);
    set @Num = 12.54;
    WITH PQ AS
    ( 
        SELECT 
            UPC, 
            Price1, 
            DBID,
            AVG(Price1) OVER (PARTITION BY UPC) AS Price1Avg
        FROM
            vProducts_PriceQty_Union
    )
    SELECT 
        PQ.UPC,
        PQ.Price1,
        PQ.Price1Avg,
        (CASE WHEN p.IsGun = 1 THEN CEILING(@Num) ELSE @Num END) AS UsingVar,
        CAST(
            (CASE WHEN P.IsGun = 1 THEN CEILING(PQ.Price1Avg) ELSE PQ.Price1 END)
             AS NUMERIC(8,2))
        AS PriceAdj,
        PQ.DBID,
        P.IsGun
    FROM
        PQ
     INNER JOIN
        products P ON PQ.UPC = P.UPC

यहाँ परिणामों का एक टुकड़ा है:

UPC             Price1      Price1Avg   UsingVar    PriceAdj    DBID  IsGun
942000899195    14.9900     14.990000   12.54       15.00       1       0
980420671300    29.9900     29.990000   12.54       30.00       1       0
980420671310    29.9900     29.990000   12.54       30.00       1       0
980426713020    29.9900     29.990000   12.54       30.00       1       0
980426713120    29.9900     29.990000   12.54       30.00       1       0
000998622130    319.0000    319.000000  13.00       319.00      1       1
000998624730    314.0000    314.000000  13.00       314.00      1       1
000998624970    419.0000    419.000000  13.00       419.00      1       1
008244284754    1015.0000   1015.000000 13.00       1015.00     2       1
010633012288    267.0000    267.000000  13.00       267.00      6       1

और यहाँ वो डेटा है जो vProducts_PriceQty_Union से आता है :

UPC             Price1  Price2  Quantity    DBID
942000899195    14.9900 0.0000  2.00        1
980420671300    29.9900 0.0000  3.00        1
980420671310    29.9900 0.0000  1.00        1
980426713020    29.9900 0.0000  2.00        1
980426713120    29.9900 0.0000  1.00        1

जैसा कि आप पहले पाँच से देख सकते हैं, जहाँ IsGun = 0, CASEनिश्चित चर का उपयोग करने वाला पहला एक्सप्रेशन, UseVar मान लौटाता है, जिसकी हम अपेक्षा करते हैं, 12.54। और पिछले पांच के लिए, यह वह मूल्य भी लौटाता है जिसकी हम उम्मीद करते हैं, 13।

लेकिन दूसरी CASEअभिव्यक्ति (बिल्कुल वही तर्क) में, PriceAdjCEILING उनमें से हर एक पर फ़ंक्शन का उपयोग करता है, भले ही IsGun = 1 हो या नहीं।

क्वेरी अपेक्षित परिणाम क्यों नहीं दे रही है?

में संघ के लिए इस्तेमाल किया तालिकाओं में से कुछ के लिए डेटा प्रकार देखने price1 और Price2 थे smallmoney और दशमलव (8.2) । मैंने तब से उन सभी को दशमलव (8,2) में बदल दिया है , लेकिन इससे परिणामों पर कोई असर नहीं पड़ा।

जवाबों:


11

समस्या को पुन: उत्पन्न करने के लिए:

SELECT *, (CASE
    WHEN IsGun=1 THEN CEILING(Price1Avg)
    ELSE Price1 END)
FROM (
    SELECT UPC, IsGun, Price1,
           AVG(CAST(Price1 AS numeric(8, 2))) OVER (PARTITION BY UPC) AS Price1Avg
    FROM (
        VALUES ('A', 0, 14.99),
               ('B', 0, 29.99),
               ('C', 1, 319.00),
               ('D', 1, 314.00)
        ) AS x(UPC, IsGun, Price1)
    ) AS sub;

यहाँ क्या होता है जो CEILING(PQ.Price1Avg)उत्पादन करता है a numeric(38, 0)

प्रलेखन के अनुसार , आउटपुट प्रकार CEILING()इनपुट के रूप में एक ही आधार डेटाटाइप का है, हालांकि स्केल (दशमलव की संख्या) बदल सकता है, जो कि यहां होता है।

  • AVG()समारोह, मेरे परीक्षणों में, देता है numeric(38, 6)
  • CEILING()हालाँकि, उस कॉलम का फ़ंक्शन आउटपुट numeric(38, 0):

जांचना:

SELECT CEILING(CAST(123.45 AS numeric(38, 6)))

वर्कअराउंड के रूप में, आप CEILING()फ़ंक्शन के आउटपुट को स्पष्ट रूप से परिवर्तित कर सकते हैं , जिससे आपको सही परिणाम मिल सकते हैं:

SELECT *, (CASE
    WHEN IsGun=1 THEN CAST(CEILING(Price1Avg) AS numeric(8, 2)) -- Explicit CAST.
    ELSE Price1 END)
FROM (
    SELECT UPC, IsGun, Price1,
           AVG(CAST(Price1 AS numeric(8, 2))) OVER (PARTITION BY UPC) AS Price1Avg
    FROM (
        VALUES ('A', 0, 14.99),
               ('B', 0, 29.99),
               ('C', 1, 319.00),
               ('D', 1, 314.00)
        ) AS x(UPC, IsGun, Price1)
    ) AS sub;

यह भी ध्यान दें कि केस स्टेटमेंट कई अलग-अलग प्रकारों को वापस नहीं कर सकते हैं, लेकिन एक IIF अभिव्यक्ति कर सकते हैं, ताकि यह उचित हो।
एडम मार्टिन

2
@AdamMartin जो सही नहीं है। एक का iifविस्तार हो जाता है case। यह दो विकल्पों में से सबसे बड़ी डेटा प्रकार की पूर्ववर्तीता के साथ प्रकार देता है । किसी भी अभिव्यक्ति के लिए एक पंक्ति में डेटा टाइप X और एक ही कॉलम के लिए दूसरी पंक्ति में डेटा प्रकार Y को वापस करना संभव नहीं है।
मार्टिन स्मिथ

@ डैनियल, सबसे उपयोगी। जैसे ही मैंने प्रत्येक आउटपुट के लिए I CAST (x AS NUMERIC (8,2)) किया, उसने वह परिणाम लौटा दिया जिसकी मुझे तलाश थी। आपको और इस समुदाय को बहुत-बहुत धन्यवाद!
रॉडनी जी
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.