گرد کردن اعداد در SQL Server: تفاوت بین تابع ROUND و حذف اعشار (Truncate)
در کار با مقادیر عددی در SQL Server، نیاز به گرد کردن یا حذف اعشار (truncate) مقادیر امری رایج است. هرچند این دو اصطلاح اغلب به جای یکدیگر به کار میروند، اما تفاوت مشخصی بین گرد کردن و حذف اعشار وجود دارد. در این مقاله به تابع SQL `ROUND` و روشهای مختلف برای حذف اعشار از مقادیر عددی میپردازیم. این شناخت دقیق برای محاسبات مالی و گزارشدهی دقیق در SQL Server بسیار حیاتی است.
فرض کنید یک جدول ساده با مقادیر عددی داریم که برای اهداف گزارشدهی مالی باید به ۲ رقم اعشار گرد شوند. جدول `FinancialData` را ایجاد میکنیم:
CREATE TABLE FinancialData (
ID INT IDENTITY(1,1),
ActualCost DECIMAL(18,4)
);
GO
سپس چند سطر داده نمونه را به این جدول اضافه میکنیم تا بتوانیم رفتار `ROUND` و روشهای حذف اعشار را مقایسه کنیم:
INSERT INTO FinancialData (ActualCost) VALUES (123.4567);
INSERT INTO FinancialData (ActualCost) VALUES (123.4547);
INSERT INTO FinancialData (ActualCost) VALUES (123.4550);
INSERT INTO FinancialData (ActualCost) VALUES (123.4650);
INSERT INTO FinancialData (ActualCost) VALUES (123.4667);
INSERT INTO FinancialData (ActualCost) VALUES (123.4647);
INSERT INTO FinancialData (ActualCost) VALUES (-123.4567);
INSERT INTO FinancialData (ActualCost) VALUES (-123.4547);
INSERT INTO FinancialData (ActualCost) VALUES (-123.4550);
GO
اکنون دادههای وارد شده را مشاهده میکنیم:
SELECT * FROM FinancialData;
GO
**استفاده از تابع SQL ROUND**
تابع `ROUND` یک عدد را به طول یا دقت مشخصی گرد میکند. ساختار کلی این تابع به صورت `ROUND(numeric_expression, length [, function])` است. پارامتر `length` مشخصکننده تعداد ارقام بعد از ممیز اعشار است که عدد باید به آن گرد شود. پارامتر اختیاری `function` تعیین میکند که آیا عملیات گرد کردن انجام شود یا حذف اعشار. اگر `function` را وارد نکنید یا مقدار آن 0 باشد (پیشفرض)، گرد کردن انجام میشود. اگر مقدار غیرصفر (مثلاً 1) باشد، تابع فقط عدد را حذف اعشار میکند. در این بخش، بر روی عملکرد گرد کردن تمرکز میکنیم.
برای گرد کردن مقدار `ActualCost` به ۲ رقم اعشار با استفاده از `ROUND`، دستور زیر را اجرا میکنیم:
SELECT ActualCost, ROUND(ActualCost, 2) AS RoundedCost FROM FinancialData;
GO
همانطور که مشاهده میشود، تابع `ROUND` مطابق با قوانین ریاضی برای گرد کردن عمل میکند؛ اگر رقم سوم بعد از اعشار ۵ یا بیشتر باشد، رقم دوم به بالا گرد میشود.
حالت جالب دیگر برای پارامتر `length` زمانی است که مقدار آن منفی باشد. در این صورت، `ROUND` عدد را به سمت چپ ممیز اعشار گرد میکند. برای مثال، برای گرد کردن به نزدیکترین دهگان یا صدگان از این روش استفاده میشود:
SELECT
ROUND(123.456, -1) AS RoundToTens, -- 120.000
ROUND(123.456, -2) AS RoundToHundreds; -- 100.000
GO
**روشهای حذف اعشار (Truncating) در SQL Server**
حذف اعشار به معنای جدا کردن قسمت اعشاری یک عدد بدون گرد کردن آن است. به عبارت دیگر، ارقام بعد از دقت مشخص شده به سادگی حذف میشوند. این رویکرد در برخی گزارشهای مالی که نیاز به حفظ بخش صحیح عدد دارند، کاربرد دارد.
**روش اول: استفاده از CAST/CONVERT برای حذف اعشار**
یکی از سادهترین راهها برای حذف اعشار، تبدیل (CAST) یک عدد به یک نوع داده عددی با دقت کمتر (مانند `DECIMAL(18,2)`) است. این روش به طور ضمنی اعشار را حذف میکند و نتیجه آن شبیه به حذف اعشار است:
SELECT ActualCost, CAST(ActualCost AS DECIMAL(18,2)) AS TruncatedCost FROM FinancialData;
GO
**روش دوم: استفاده از FLOOR و CEILING برای حذف اعشار**
توابع `FLOOR` و `CEILING` به ترتیب یک عدد را به نزدیکترین عدد صحیح کوچکتر یا بزرگتر گرد میکنند. میتوان از ترکیب این توابع با ضرب و تقسیم برای حذف اعشار به یک دقت مشخص استفاده کرد.
برای مقادیر مثبت:
تابع `FLOOR` میتواند برای حذف اعشار به پایین استفاده شود. با ضرب در یک عامل مقیاس (مثلاً 100 برای 2 رقم اعشار)، اعمال `FLOOR` و سپس تقسیم مجدد، میتوان بخش اعشاری را حفظ کرد:
SELECT ActualCost, FLOOR(ActualCost * 100) / 100.0 AS TruncatedWithFloor
FROM FinancialData
WHERE ActualCost >= 0;
GO
برای مقادیر منفی:
تابع `CEILING` میتواند برای حذف اعشار به بالا برای اعداد منفی استفاده شود. این رویکرد تضمین میکند که حذف اعشار به سمت صفر انجام میشود، همانند رفتار `CAST` برای اعداد منفی:
SELECT ActualCost, CEILING(ActualCost * 100) / 100.0 AS TruncatedWithCeiling
FROM FinancialData
WHERE ActualCost < 0;
GO
برای استفاده از `FLOOR` برای مقادیر منفی به منظور حذف اعشار به سمت صفر، میتوان از منطق شرطی استفاده کرد:
SELECT ActualCost,
CASE WHEN ActualCost > 0 THEN FLOOR(ActualCost * 100) / 100.0
ELSE CEILING(ActualCost * 100) / 100.0 END AS TruncatedValue
FROM FinancialData;
GO
**مقایسه گرد کردن و حذف اعشار**
درک تفاوت بین `ROUND` و حذف اعشار برای محاسبات دقیق در SQL Server بسیار مهم است. `ROUND` مقدار را به نزدیکترین عدد صحیح گرد میکند و به این معنی است که اگر رقم بعدی بزرگتر از 5 باشد، به بالا گرد میشود و اگر کمتر از 5 باشد، به پایین گرد میشود. در مقابل، حذف اعشار صرفاً ارقام اضافی را بدون توجه به مقدار آنها حذف میکند.
به عنوان مثال، برای `123.4567`:
* `ROUND(123.4567, 2)` نتیجه `123.46` را میدهد (گرد شده به بالا).
* `CAST(123.4567 AS DECIMAL(18,2))` نتیجه `123.45` را میدهد (ارقام اضافی حذف شده).
برای `123.4547`:
* `ROUND(123.4547, 2)` نتیجه `123.45` را میدهد (گرد شده به پایین).
* `CAST(123.4547 AS DECIMAL(18,2))` نتیجه `123.45` را میدهد (ارقام اضافی حذف شده).
در نهایت، برای پاکسازی جدول موقت:
DROP TABLE FinancialData;
GO