דרך מעניינת להסתכל על טבלאות היא כעל קבוצות של רשומות.
נכון שהדימוי האינטואיטיבי הוא דווקא של רשימה מסודרת (טבלה..) אבל לסדר אין חשיבות והטבלה נשארת אותה טבלה ללא קשר לאופן המיון הלוגי או הפיזי של הרשומות (זו כנראה אחת הסיבות להתעקשותה של Microsoft לא לאפשר ביצוע Order By ב-View), ובין טבלאות ניתן לבצע פעולות חיתוך ואיחוד כפי שלמדנו במבוא לתורת הקבוצות..
לצורך ההמחשה ניצור שתי טבלאות בעלות מבנה זהה, ונכניס לתוכן נתונים – חלקם זהים וחלקם שונים:
Use tempdb;
Go
If Object_Id('Tbl1') Is Not Null Drop Table Tbl1;
Go
Create Table Tbl1(ID Int Primary Key,
Name Varchar(10),
Date DateTime);
Go
Insert
Into Tbl1
Select 1,'Anat','19700101' Union All
Select 2,'Beni','19750201' Union All
Select 3,'Galit','19770301' Union All
Select 4,'Dana','19800401';
Go
If Object_Id('Tbl2') Is Not Null Drop Table Tbl2;
Go
Create Table Tbl2(ID Int Primary Key,
Name Varchar(10),
Date DateTime);
Go
Insert
Into Tbl2
Select 3,'Galit','19770301' Union All
Select 4,'Dana','19800401' Union All
Select 5,'Eli','19880501' Union All
Select 6,'Hila','19900601';
Go
חיתוך (השטח הכחול המשותף לשתי הטבלאות) מתקבל על ידי Join:
Select *
From Tbl1
Inner Join Tbl2
On Tbl1.ID=Tbl2.ID;
Go
השטח של Tbl1 על ידי Left Join בינה לבין Tbl2 (ואפשר להבחין בפלט היכן החלק התכול והיכן הכחול):
Select *
From Tbl1
Left Join Tbl2
On Tbl1.ID=Tbl2.ID;
Go
את החלק הכחול ללא התכול ניתן להציג על ידי הוספת תנאי Is Null על Tbl2.
השטח של Tbl2 על ידי Right Join:
Select *
From Tbl1
Right Join Tbl2
On Tbl1.ID=Tbl2.ID;
Go
האיחוד יכול להתקבל בעזרת Full Join:
Select *
From Tbl1
Full Join Tbl2
On Tbl1.ID=Tbl2.ID;
Go
את השטחים התכולים ללא החיתוך הכחול ניתן לקבל על ידי תנאי Is Null על כל אחת מהטבלאות, ויחס Or בינהם.
רגע, איחוד זה לא Union?
בוודאי- נכון שנהוג להציג את פעולת Join כ"טבלה ליד טבלה" (או שתי טבלאות במקביל) ואת פעולת Union כ"טבלה מעל טבלה" (או שתי טבלאות בטור) אבל הגמישות של ה-Join מאפשר הרבה יותר מהצפוי, כולל ביצוע Union.
נתחיל עם Union פשוט שמבצע גם Distinct ומפלטר רשומות כפולות:
Select *
From Tbl1
Union
Select *
From Tbl2;
Select IsNull(Tbl1.ID,Tbl2.ID) ID,
IsNull(Tbl1.Name,Tbl2.Name) Name,
IsNull(Tbl1.Date,Tbl2.Date) Date
From Tbl1
Full Join Tbl2
On Tbl1.ID=Tbl2.ID;
Go
ונמשיך עם Union All שמציג את כל הרשומות, כולל כפילויות:
Select *
From Tbl1
Union All
Select *
From Tbl2;
Select IsNull(Tbl1.ID,Tbl2.ID) ID,
IsNull(Tbl1.Name,Tbl2.Name) Name,
IsNull(Tbl1.Date,Tbl2.Date) Date
From Tbl1
Full Join Tbl2
On 1=2;
Go
במקרה זה צירפנו לאופרטור On תנאי שאף פעם אינו מתקיים (1=2) וכתוצאה מכך לא נוצרה אף התאמה (גם כשכן הייתה) וכל טבלה הוצגה בנפרד.
באופן דומה- גם את פעולת החיסור נוכל לבצע הן בעזרת Except הפשוט והאינטואיטיבי והן בעזרת Left Join ותנאי Is Null:
Select *
From Tbl1
Except
Select *
From Tbl2;
Select Tbl1.*
From Tbl1
Left Join Tbl2
On Tbl1.ID=Tbl2.ID
Where Tbl2.ID Is Null;
Go
כדאי אולי לצרף הסתייגות קטנה לפרוטוקול: כשיש Nulls ובעיקר כשיש השוואה בין Nulls מקבלים תוצאות לא תמיד צפויות, והיתרון של Union ו-Except שהם גם פשוטים מבחינת הסינטקס וההבנה האינטואיטיבית, וגם ידידותיים מבחינת התוצאות במקרה של Nulls.