sql - এসকিউএল থেকে "শূন্য দ্বারা বিভক্ত" এড়াতে কিভাবে?




sql-server sql-server-2005 (12)

শূন্য দ্বারা ভাগ করে নেওয়ার চেষ্টা করার সময় এটি আমার অবস্থার জন্য সর্বোত্তম সমাধান বলে মনে হচ্ছে, যা আমার ডেটাতে ঘটে।

ধরুন আপনি বিভিন্ন স্কুল ক্লাবে পুরুষ-মহিলা অনুপাত গণনা করতে চান, তবে আপনি আবিষ্কার করেন যে নিম্নোক্ত প্রশ্নটি ব্যর্থ হয় এবং রিং ক্লাবে লর্ডের অনুপাত গণনা করার চেষ্টা করে একটি বিভাজন-শূন্য ত্রুটি সংশোধন করে, যার কোন মহিলা নেই :

SELECT club_id, males, females, males/females AS ratio
  FROM school_clubs;

আপনি শূন্য দ্বারা বিভাগ এড়াতে ফাংশন NULLIF ব্যবহার করতে পারেন। NULLIF দুটি এক্সপ্রেশন তুলনা করে এবং যদি তারা সমান বা প্রথম অভিব্যক্তি অন্যথায় নাল না হয়।

প্রশ্নটি আবার লিখুন:

SELECT club_id, males, females, males/NULLIF(females, 0) AS ratio
  FROM school_clubs;

NULL দ্বারা ভাগ করা কোন সংখ্যা NULL দেয়, এবং কোন ত্রুটি উত্পন্ন হয়।

আমার এই ত্রুটি বার্তা আছে:

বার্তা 8134, স্তর 16, রাজ্য 1, লাইন 1 শূন্য ত্রুটি দ্বারা বিভক্ত।

এসকিউএল কোড লেখার সবচেয়ে ভাল উপায় কী যে আমি আর কখনো এই ত্রুটি বার্তাটি দেখতে পাব না?

আমি নিম্নলিখিত কোনটি করতে পারে:

  • একটি বিভাগ যেখানে যোগ করুন যাতে আমার divisor শূন্য না

অথবা

  • আমি একটি কেস বিবৃতি যোগ করতে পারে, যাতে শূন্য জন্য একটি বিশেষ চিকিত্সা আছে।

একটি NULLIF ধারা ব্যবহার করার সেরা উপায়?

ভাল উপায় আছে, বা কিভাবে এই প্রয়োগ করা যেতে পারে?


  1. Divisor অ-শূন্য হতে বাধ্য করে এমন একটি চেক সীমা যোগ করুন
  2. ফর্মটিতে একটি বৈধতা যোগ করুন যাতে ব্যবহারকারী এই ক্ষেত্রটিতে শূন্য মানগুলি প্রবেশ করতে না পারে।

আপনি অন্তত একটি ত্রুটির ভঙ্গ থেকে কোয়েরিটি বন্ধ করতে এবং NULL দ্বারা একটি বিভাগ থাকলে NULL ফিরে আসতে পারেন:

SELECT a / NULLIF(b, 0) FROM t 

যাইহোক, আমি জিরোর সাথে কোলেশে রূপান্তর করব না যেমন এটি অন্য উত্তরগুলিতে দেখানো হয়েছে যা অনেকগুলি আপভোট পেয়েছে। এটি একটি গাণিতিক অর্থে সম্পূর্ণরূপে ভুল, এবং এটিও বিপজ্জনক কারণ আপনার অ্যাপ্লিকেশন সম্ভবত ভুল এবং বিভ্রান্তিকর ফলাফলগুলি ফেরত দেবে।


আপনি এই প্রশ্নটির শুরুতেও এটি করতে পারেন:

SET ARITHABORT OFF 
SET ANSI_WARNINGS OFF

তাই যদি আপনার 100/0 মত কিছু আছে এটি ফিরে আসবে। আমি কেবল সাধারণ প্রশ্নগুলির জন্য এটি করেছি, তাই আমি জানি না এটি কীভাবে দীর্ঘ / জটিলগুলি প্রভাবিত করবে।


একটি "শূন্য দ্বারা বিভাগ" এড়ানোর জন্য আমরা এটির মতো প্রোগ্রাম করেছি:

Select Case when divisor=0 then null
Else dividend / divisor
End ,,,

কিন্তু এখানে এটি করার একটি চমৎকার উপায়:

Select dividend / NULLIF(divisor, 0) ...

এখন একমাত্র সমস্যা হল NullIf বিট মনে রাখা, যদি আমি "/" কী ব্যবহার করি।


এখানে একটি পরিস্থিতি যেখানে আপনি শূন্য দ্বারা বিভক্ত করতে পারেন। ব্যবসায় নিয়ম হল জায় হিসাবের হিসাব করা, আপনি একটি নির্দিষ্ট সময়ের জন্য বিক্রি পণ্য মূল্য, এটি বার্ষিককরণ। আপনি বার্ষিককৃত নম্বর আছে, আপনি সময়ের জন্য গড় জায় দ্বারা বিভক্ত।

আমি তিন মাস সময়ের মধ্যে ঘটতে তালিকা সংখ্যা সক্রিয় গণনা করছি। আমি হিসাব করেছি যে আমার কাছে 1000 ডলারের তিন মাস সময়কালে বিক্রি করা সামগ্রীর মূল্য রয়েছে। বিক্রয় বার্ষিক হার $ 4,000 ($ 1,000 / 3) * 12। প্রারম্ভিক তালিকা 0। শেষ পরিসংখ্যান হল 0. আমার গড় জায় এখন 0। প্রতি বছর $ 4000 বিক্রি হয় এবং কোনও তালিকা নেই। এই ফল একটি অসীম সংখ্যা ফলন। এর মানে হল যে আমার সমস্ত জায় গ্রাহক দ্বারা রূপান্তরিত এবং ক্রয় করা হচ্ছে।

এটি জায় বিনিময় গণনা করার একটি ব্যবসায় নিয়ম।


কলিং প্রোগ্রামে প্রচারিত হওয়ার সময় আপনি সঠিকভাবে ত্রুটিটি পরিচালনা করতে পারেন (অথবা আপনি যা চান তা উপেক্ষা করুন)। সি # সিএলিতে যেকোনো ত্রুটি ঘটেছে এমন একটি ব্যতিক্রম যা আমি ধরতে পারি এবং তারপর আমার কোডে হ্যান্ডেল করতে পারি, ঠিক যেমন অন্য কোনো ত্রুটি।

আমি বেস্কের সাথে একমত যে আপনি ভুলটি লুকাতে চান না। আপনি একটি পারমাণবিক চুল্লির সাথে ডিল করা হতে পারে না কিন্তু সাধারণভাবে ত্রুটি লুকানোর প্রোগ্রামিং অনুশীলন খারাপ। অধিকাংশ আধুনিক প্রোগ্রামিং ভাষা একটি ত্রুটির / স্থিতি কোডের সাথে প্রকৃত প্রত্যাবর্তনের মানকে হ্রাস করার জন্য কাঠামোগত ব্যতিক্রম হ্যান্ডলিং বাস্তবায়নের একটি কারণ। আপনি গণিত করছেন যখন এই বিশেষ করে সত্য। সবচেয়ে বড় সমস্যা হল যে আপনি সঠিকভাবে গণনা করা 0 টি ফেরত পেয়েছেন বা একটি ত্রুটির ফলাফল হিসাবে 0 এর মধ্যে পার্থক্য করতে পারছেন না। এর পরিবর্তে যেকোন মান ফেরত দেওয়া হয় এবং যদি কিছু ভুল হয় তবে ব্যতিক্রমটি নিক্ষিপ্ত হয়। আপনি ডাটাবেস অ্যাক্সেস করছেন কীভাবে এবং আপনি কোন ভাষা ব্যবহার করছেন তার উপর নির্ভর করে এটি অবশ্যই ভিন্ন হবে তবে আপনি সর্বদা একটি ত্রুটি বার্তা পেতে সক্ষম হবেন যা আপনি মোকাবেলা করতে পারেন।

try
{
    Database.ComputePercentage();
}
catch (SqlException e)
{
    // now you can handle the exception or at least log that the exception was thrown if you choose not to handle it
    // Exception Details: System.Data.SqlClient.SqlException: Divide by zero error encountered.
}

কোন বিভাগ ব্যবহার করে তথ্য ফিল্টার করুন যাতে আপনাকে 0 মান না পান।


যদি আপনি শূন্যটি ফেরত দিতে চান তবে কোনও শূন্য ডেভিশন ঘটবে, আপনি এটি ব্যবহার করতে পারেন:

SELECT COALESCE(dividend / NULLIF(divisor,0), 0) FROM sometable

শূন্য যে প্রতিটি divisor জন্য, আপনি ফলাফল সেট একটি শূন্য পেতে হবে।


শূন্য সঙ্গে "শূন্য দ্বারা বিভক্ত" প্রতিস্থাপন বিতর্কিত - কিন্তু এটি একমাত্র বিকল্প নয়। কিছু ক্ষেত্রে 1 দিয়ে প্রতিস্থাপন করা হয় (যুক্তিসঙ্গত) উপযুক্ত। আমি প্রায়ই ব্যবহার করে নিজেকে খুঁজে

 ISNULL(Numerator/NULLIF(Divisor,0),1)

যখন আমি স্ক্রো / কাউন্টগুলিতে শিফটে দেখছি, এবং আমার কাছে ডেটা না থাকলে 1 ডিফল্ট করতে চাই। উদাহরণ স্বরূপ

NewScore = OldScore *  ISNULL(NewSampleScore/NULLIF(OldSampleScore,0),1) 

প্রায়শই না, আমি প্রকৃতপক্ষে অন্য কোথাও এই অনুপাতটি গণনা করেছি (অন্তত কারণ এটি নিম্ন সূচকগুলির জন্য কিছু খুব বড় সমন্বয় উপাদান নিক্ষেপ করতে পারে না। এই ক্ষেত্রে আমি সাধারনত ওল্ডস্প্যান্ডস্কোরের জন্য নিয়ন্ত্রণ করতে চাইছি যা থ্রেশহোল্ডের চেয়ে বেশি; কিন্তু কখনও কখনও 'হ্যাক' উপযুক্ত।


NULLIF(exp,0) ব্যবহার করুন NULLIF(exp,0) কিন্তু এই ভাবে - NULLIF(ISNULL(exp,0),0)

NULLIF(exp,0) NULLIF(ISNULL(exp,0),0) null কিন্তু NULLIF(ISNULL(exp,0),0) বিরতি না দেয়


CREATE FUNCTION dbo.Divide(@Numerator Real, @Denominator Real)
RETURNS Real AS
/*
Purpose:      Handle Division by Zero errors
Description:  User Defined Scalar Function
Parameter(s): @Numerator and @Denominator

Test it:

SELECT 'Numerator = 0' Division, dbo.fn_CORP_Divide(0,16) Results
UNION ALL
SELECT 'Denominator = 0', dbo.fn_CORP_Divide(16,0)
UNION ALL
SELECT 'Numerator is NULL', dbo.fn_CORP_Divide(NULL,16)
UNION ALL
SELECT 'Denominator is NULL', dbo.fn_CORP_Divide(16,NULL)
UNION ALL
SELECT 'Numerator & Denominator is NULL', dbo.fn_CORP_Divide(NULL,NULL)
UNION ALL
SELECT 'Numerator & Denominator = 0', dbo.fn_CORP_Divide(0,0)
UNION ALL
SELECT '16 / 4', dbo.fn_CORP_Divide(16,4)
UNION ALL
SELECT '16 / 3', dbo.fn_CORP_Divide(16,3)

*/
BEGIN
    RETURN
        CASE WHEN @Denominator = 0 THEN
            NULL
        ELSE
            @Numerator / @Denominator
        END
END
GO






sql-server-2008