مقایسه عملگرهای NOT EQUAL در WHERE SQL Server و بهینه سازی

مقایسه عملگرهای NOT EQUAL در شرط WHERE SQL Server: کدام گزینه بهینه‌تر است؟

دستور WHERE در SQL برای فیلتر کردن رکوردها در یک جدول استفاده می‌شود تا فقط سطرهایی که یک شرط مشخص را برآورده می‌کنند، در نتایج گنجانده شوند. این دستور با عبارت‌های SELECT، UPDATE و DELETE کاربرد دارد. این مقاله بر روی چگونگی استفاده از عملگر NOT EQUAL در شرط WHERE در SQL Server تمرکز دارد.

SQL Server چندین عملگر NOT EQUAL را برای مقایسه ارائه می‌دهد. این عملگر برای بررسی اینکه آیا یک عبارت با عبارت دیگری برابر نیست، به کار می‌رود. در ادامه به بررسی عملگرهای زیر خواهیم پرداخت:

<> (Less than or Greater than)

!= (Exclamation mark followed by Equal sign)

NOT EXISTS

NOT IN

اجازه دهید یک پایگاه داده و جدول نمونه ایجاد کنیم تا کاربرد عملگر NOT EQUAL در شرط WHERE در SQL را نمایش دهیم.


USE [master]
GO

IF EXISTS (SELECT * FROM sys.databases WHERE name = 'NOT_EQUAL_DB')
BEGIN
    ALTER DATABASE [NOT_EQUAL_DB] SET SINGLE_USER WITH ROLLBACK IMMEDIATE
    DROP DATABASE [NOT_EQUAL_DB]
END
GO

CREATE DATABASE [NOT_EQUAL_DB]
GO

USE [NOT_EQUAL_DB]
GO

CREATE TABLE [dbo].[Employee]
(
    [EmployeeId] [int] IDENTITY(1,1) NOT NULL,
    [EmployeeName] [varchar](50) NULL,
    [Department] [varchar](50) NULL,
    [Salary] [decimal](18, 2) NULL,
    [City] [varchar](50) NULL,
 CONSTRAINT [PK_Employee] PRIMARY KEY CLUSTERED ([EmployeeId] ASC)
)
GO

INSERT INTO [dbo].[Employee] ([EmployeeName], [Department], [Salary], [City]) VALUES
('John Smith', 'IT', 60000.00, 'New York'),
('Jane Doe', 'HR', 55000.00, 'London'),
('Peter Jones', 'IT', 62000.00, 'New York'),
('Mary White', 'Finance', 70000.00, 'Paris'),
('David Green', 'HR', 58000.00, 'London'),
('Emily Black', 'IT', 61000.00, 'New York'),
('Chris Brown', 'Finance', 68000.00, 'Paris'),
('Sarah Davis', 'HR', 56000.00, 'London'),
('Michael Johnson', 'IT', 63000.00, 'New York'),
('Laura Wilson', 'Marketing', 59000.00, 'Berlin'),
('Robert Taylor', 'Marketing', 60000.00, 'Berlin'),
('Patricia Moore', 'IT', 65000.00, 'New York')
GO

عملگر <> یک عملگر استاندارد SQL برای «برابر نبودن» است و در سیستم‌های پایگاه داده مختلف پشتیبانی می‌شود. این عملگر برای فیلتر کردن رکوردهایی که مقداری خاص را ندارند، استفاده می‌شود:


SELECT
    [EmployeeId],
    [EmployeeName],
    [Department],
    [Salary],
    [City]
FROM
    [dbo].[Employee]
WHERE
    [Department] <> 'IT'

خروجی این کوئری تمام رکوردهای کارمندانی را نشان می‌دهد که بخش (Department) آن‌ها «IT» نیست. این نتایج شامل کارمندانی از بخش‌های HR، Finance و Marketing است.

عملگر != نیز یک عملگر «برابر نبودن» است، اما بخشی از استاندارد ANSI SQL نیست. این عملگر به طور خاص در SQL Server و برخی دیگر از سیستم‌های پایگاه داده مانند MySQL و PostgreSQL پشتیبانی می‌شود، اما در Oracle خیر. عملکرد آن در SQL Server مشابه <> است:


SELECT
    [EmployeeId],
    [EmployeeName],
    [Department],
    [Salary],
    [City]
FROM
    [dbo].[Employee]
WHERE
    [Department] != 'IT'

خروجی این کوئری که از عملگر != استفاده می‌کند، مشابه عملگر <> است و نتایج یکسانی را برمی‌گرداند.

عملگرهای <> و != در SQL Server رفتار یکسانی دارند. انتخاب بین آن‌ها اغلب به ترجیح شخصی یا استانداردهای کدنویسی درون یک سازمان بستگی دارد. با این حال، برای حداکثر سازگاری در سیستم‌های پایگاه داده مختلف، عموماً توصیه می‌شود از عملگر <> استفاده شود، زیرا بخشی از استاندارد ANSI SQL است.

یک نکته مهم در مورد نحوه برخورد این عملگرها با مقادیر NULL است. در SQL، مقدار NULL با هیچ چیز برابر نیست، حتی با خودش. بنابراین، اگر سعی کنید یک ستون با مقدار NULL را با استفاده از <> یا != مقایسه کنید، آن سطر در نتایج گنجانده نخواهد شد. برای مثال، اگر کارمندانی با بخش NULL داشته باشیم:


SELECT
    [EmployeeId],
    [EmployeeName],
    [Department],
    [Salary],
    [City]
FROM
    [dbo].[Employee]
WHERE
    [Department] <> 'IT'

کوئری بالا رکوردهایی را بازمی‌گرداند که Department آن‌ها «IT» نیست و Department آن‌ها NULL نیست. اگر می‌خواهید رکوردهایی را که Department آن‌ها NULL است نیز شامل شود، باید به صراحت آن را بررسی کنید:


SELECT
    [EmployeeId],
    [EmployeeName],
    [Department],
    [Salary],
    [City]
FROM
    [dbo].[Employee]
WHERE
    [Department] <> 'IT' OR [Department] IS NULL

عملگر NOT IN برای تعیین اینکه آیا یک مقدار در لیستی از مقادیر مشخص یا در مجموعه نتایج یک ساب‌کوئری وجود ندارد، استفاده می‌شود. این عملگر می‌تواند زمانی مفید باشد که نیاز به حذف چندین مقدار خاص داشته باشید:


SELECT
    [EmployeeId],
    [EmployeeName],
    [Department],
    [Salary],
    [City]
FROM
    [dbo].[Employee]
WHERE
    [Department] NOT IN ('IT', 'Finance')

مشابه عملگرهای <> و !=، عملگر NOT IN نیز رفتار خاصی با مقادیر NULL دارد. اگر هر مقداری در لیست (یا نتیجه ساب‌کوئری) عملگر NOT IN، NULL باشد، کل شرط NOT IN برای همه سطرها به UNKNOWN ارزیابی می‌شود و بنابراین هیچ سطری برگردانده نخواهد شد. این یک نکته حیاتی و یک دام رایج است:


-- اگر 'NULL' در لیست باشد، نتایج غیرمنتظره خواهد بود (هیچ رکوردی برنمی‌گردد)
SELECT
    [EmployeeId],
    [EmployeeName],
    [Department],
    [Salary],
    [City]
FROM
    [dbo].[Employee]
WHERE
    [Department] NOT IN ('IT', NULL)

برای استفاده صحیح از NOT IN در صورتی که مقادیر NULL ممکن است وجود داشته باشند، مطمئن شوید که لیست مقادیر یا نتیجه ساب‌کوئری حاوی NULL نیست، یا صراحتاً NULLها را در منطق کوئری خود مدیریت کنید. به عنوان مثال، فیلتر کردن NULLها از ساب‌کوئری:


SELECT
    [EmployeeId],
    [EmployeeName],
    [Department],
    [Salary],
    [City]
FROM
    [dbo].[Employee]
WHERE
    [Department] NOT IN (SELECT [Department] FROM [dbo].[Employee] WHERE [Department] IS NOT NULL)

عملگر NOT EXISTS برای تعیین اینکه آیا یک ساب‌کوئری هیچ سطری را برنمی‌گرداند، استفاده می‌شود. اگر ساب‌کوئری هیچ سطری را برنگرداند، شرط NOT EXISTS صحیح (TRUE) است. این عملگر به ویژه برای فیلتر کردن رکوردهای جدول اصلی بر اساس عدم وجود رکوردهای مرتبط در جدول دیگر مفید است.

بر خلاف NOT IN، عملگر NOT EXISTS در نحوه برخورد با مقادیر NULL در ساب‌کوئری، کارآمدتر و قابل پیش‌بینی‌تر است، زیرا مقادیر NULL در ساب‌کوئری تاثیری بر نتیجه نهایی NOT EXISTS نمی‌گذارند. مثال زیر کارمندانی را انتخاب می‌کند که در بخش IT نیستند:


SELECT
    [EmployeeId],
    [EmployeeName],
    [Department],
    [Salary],
    [City]
FROM
    [dbo].[Employee] e
WHERE NOT EXISTS (
    SELECT 1
    FROM [dbo].[Employee]
    WHERE [Department] = 'IT' AND [EmployeeId] = e.[EmployeeId]
)

خروجی این کوئری نیز مشابه مثال‌های قبلی است که کارمندانی را از بخش‌های غیر IT بازمی‌گرداند.

وقتی صحبت از عملکرد می‌شود، عملگرهای <> و != عموماً سریع‌ترین گزینه‌ها برای مقایسه‌های ساده تک مقداری هستند. NOT IN می‌تواند برای لیست‌های کوتاه مقادیر یا ساب‌کوئری‌های کوچک کارآمد باشد، اما باید مراقب رفتار آن با NULLها بود. NOT EXISTS برای ساب‌کوئری‌ها معمولاً عملکرد بهتری نسبت به NOT IN دارد، به خصوص در مواجهه با NULLها یا ساب‌کوئری‌های پیچیده‌تر، زیرا NOT EXISTS به محض یافتن اولین تطابق متوقف می‌شود.

برای بررسی دقیق‌تر، می‌توانیم زمان اجرای کوئری‌ها و طرح‌های اجرایی (Execution Plans) آن‌ها را مقایسه کنیم. به عنوان مثال، می‌توانید از دستورات SET STATISTICS IO ON و SET STATISTICS TIME ON برای مشاهده جزئیات منابع مصرفی هر کوئری استفاده کنید. اما در بیشتر سناریوهای معمول و برای مقایسه‌های ساده NOT EQUAL، عملگرهای <> و != به دلیل سادگی و کارایی استانداردشان، انتخاب‌های مناسبی هستند.

NOT EQUAL
Comments (0)
Add Comment