مقایسه دقیق نتایج دو کوئری در SQL Server با تکنیکهای پیشرفته
گاهی نیاز پیدا میکنیم که نتایج دو کوئری (پرس و جو) را با یکدیگر مقایسه کنیم. این کار ممکن است برای شناسایی ردیفهای مشابه، ردیفهای موجود فقط در یکی از کوئریها، یا برای اطمینان از صحت دادهها پس از اعمال تغییرات یا بهروزرسانیها باشد. در ادامه، روشهای متداول برای مقایسه خروجی دو کوئری در SQL Server را بررسی میکنیم.
برای نشان دادن این روشها، دو جدول نمونه ایجاد میکنیم و دادههایی را در آنها درج میکنیم تا وضعیتهای مختلف را پوشش دهیم.
CREATE TABLE EmployeeA (
EmployeeID INT,
EmployeeName VARCHAR(50),
Department VARCHAR(50)
);
CREATE TABLE EmployeeB (
EmployeeID INT,
EmployeeName VARCHAR(50),
Department VARCHAR(50)
);
INSERT INTO EmployeeA (EmployeeID, EmployeeName, Department) VALUES
(1, 'Alice', 'HR'),
(2, 'Bob', 'IT'),
(3, 'Charlie', 'Finance'),
(4, 'David', 'Sales');
INSERT INTO EmployeeB (EmployeeID, EmployeeName, Department) VALUES
(1, 'Alice', 'HR'),
(2, 'Bob', 'IT'),
(5, 'Eve', 'Marketing'),
(6, 'Frank', 'HR');
با این دادهها، میتوانیم تفاوتها و شباهتهای بین دو جدول را مشاهده کنیم.
استفاده از عبارت EXCEPT
عبارت `EXCEPT` برای بازگرداندن تمام ردیفهای متمایزی استفاده میشود که در نتیجه کوئری اول هستند اما در نتیجه کوئری دوم وجود ندارند. این عمل برای یافتن ردیفهایی که فقط در مجموعه اول حضور دارند، بسیار مفید است.
SELECT EmployeeID, EmployeeName, Department FROM EmployeeA
EXCEPT
SELECT EmployeeID, EmployeeName, Department FROM EmployeeB;
این کوئری ردیفهایی از `EmployeeA` را برمیگرداند که هیچ مطابقتی در `EmployeeB` ندارند. نتیجه شامل کارمندان چارلی و دیوید خواهد بود.
SELECT EmployeeID, EmployeeName, Department FROM EmployeeB
EXCEPT
SELECT EmployeeID, EmployeeName, Department FROM EmployeeA;
این کوئری ردیفهایی از `EmployeeB` را بازمیگرداند که هیچ مطابقتی در `EmployeeA` ندارند. نتیجه شامل کارمندان ایو و فرانک خواهد بود.
استفاده از NOT EXISTS
عبارت `NOT EXISTS` نیز روشی قدرتمند برای یافتن ردیفهایی است که در یک مجموعه داده وجود دارند اما در مجموعه داده دیگر غایب هستند. این روش انعطافپذیری بیشتری در شرایط پیوستن (Join conditions) ارائه میدهد.
SELECT A.EmployeeID, A.EmployeeName, A.Department
FROM EmployeeA AS A
WHERE NOT EXISTS (
SELECT 1
FROM EmployeeB AS B
WHERE A.EmployeeID = B.EmployeeID
AND A.EmployeeName = B.EmployeeName
AND A.Department = B.Department
);
این کوئری تمام ردیفهای `EmployeeA` را بازمیگرداند که هیچ ردیف مطابق با `EmployeeID`, `EmployeeName` و `Department` در `EmployeeB` ندارند. نتیجه مشابه `EXCEPT` بالا خواهد بود (کارمندان چارلی و دیوید).
SELECT B.EmployeeID, B.EmployeeName, B.Department
FROM EmployeeB AS B
WHERE NOT EXISTS (
SELECT 1
FROM EmployeeA AS A
WHERE B.EmployeeID = A.EmployeeID
AND B.EmployeeName = A.EmployeeName
AND B.Department = A.Department
);
به همین ترتیب، این کوئری تمام ردیفهای `EmployeeB` را بازمیگرداند که هیچ ردیف مطابق در `EmployeeA` ندارند (کارمندان ایو و فرانک).
استفاده از FULL JOIN
`FULL JOIN` (یا `FULL OUTER JOIN`) به ما اجازه میدهد تا تمام ردیفها را از هر دو کوئری ترکیب کنیم و بتوانیم تفاوتها را با بررسی مقادیر `NULL` در ستونهای غیرمشترک شناسایی کنیم. این روش برای مشاهده ردیفهای منحصربهفرد در هر دو مجموعه و همچنین ردیفهای مشترک مفید است.
SELECT
A.EmployeeID AS A_EmployeeID,
A.EmployeeName AS A_EmployeeName,
A.Department AS A_Department,
B.EmployeeID AS B_EmployeeID,
B.EmployeeName AS B_EmployeeName,
B.Department AS B_Department
FROM EmployeeA AS A
FULL JOIN EmployeeB AS B ON A.EmployeeID = B.EmployeeID
WHERE A.EmployeeID IS NULL OR B.EmployeeID IS NULL;
این کوئری تمام ردیفهایی را نشان میدهد که فقط در `EmployeeA` (ستونهای `B` حاوی `NULL` خواهند بود) یا فقط در `EmployeeB` (ستونهای `A` حاوی `NULL` خواهند بود) وجود دارند. با این روش، میتوانیم بهطور همزمان تمام ردیفهای متمایز از هر دو جدول را مشاهده کنیم.
مفهوم MINUS در مقایسه کوئریها
در برخی سیستمهای مدیریت پایگاه داده مانند اوراکل، عملگر `MINUS` عملکردی مشابه `EXCEPT` در SQL Server دارد. هر دو برای یافتن ردیفهای متمایزی که در مجموعه نتایج کوئری اول هستند اما در مجموعه نتایج کوئری دوم نیستند، استفاده میشوند. در SQL Server، برای دستیابی به این نتیجه، از عبارت `EXCEPT` استفاده میشود و `MINUS` به عنوان یک عملگر وجود ندارد.