שימושים מורכבים ב-Join
- Geri Reshef

- Sep 24
- 7 min read
אני מניח שכל מי שקורא את הפוסט יודע מה ההבדל בין Inner Join ל-Left Join, והכוונה שלי היא לטפל במקרה יותר מורכב. נניח שיש לנו 3 טבלאות:
Customers
Orders
OrderItems
יש כמובן Foreign Key מהטבלה השלישית לשנייה, ומהשנייה לראשונה.
להלן הקוד ליצירת הטבלאות ולאיכלוסן בנתונים:
Use tempdb;
Go
Drop Table If Exists OrderItems;
Drop Table If Exists Orders;
Drop Table If Exists Customers;
CREATE TABLE Customers (
CustomerID INT IDENTITY(1,1) NOT NULL,
FirstName NVARCHAR(100) NOT NULL,
LastName NVARCHAR(100) NOT NULL,
Email NVARCHAR(255) NOT NULL,
RegistrationDate DATETIME2 DEFAULT GETDATE(),
-- Primary Key constraint
CONSTRAINT PK_Customers PRIMARY KEY (CustomerID),
-- Unique constraint to prevent duplicate emails
CONSTRAINT UQ_Customers_Email UNIQUE (Email)
);
CREATE TABLE Orders (
OrderID INT IDENTITY(1,1) NOT NULL,
CustomerID INT NOT NULL,
OrderDate DATETIME2 DEFAULT GETDATE(),
TotalAmount DECIMAL(10, 2) NOT NULL,
ShippingAddress NVARCHAR(500) NULL,
-- Primary Key constraint
CONSTRAINT PK_Orders PRIMARY KEY (OrderID),
-- Foreign Key constraint linking to the Customers table
CONSTRAINT FK_Orders_Customers FOREIGN KEY (CustomerID)
REFERENCES Customers (CustomerID)
ON DELETE NO ACTION -- Prevents deleting a customer if they have orders
);
CREATE TABLE OrderItems (
OrderItemID INT IDENTITY(1,1) NOT NULL,
OrderID INT NOT NULL,
ProductID INT NOT NULL,
Quantity INT NOT NULL,
UnitPrice DECIMAL(10, 2) NOT NULL,
-- Primary Key constraint
CONSTRAINT PK_OrderItems PRIMARY KEY (OrderItemID),
-- Foreign Key constraint linking to the Orders table
CONSTRAINT FK_OrderItems_Orders FOREIGN KEY (OrderID)
REFERENCES Orders (OrderID)
ON DELETE CASCADE -- Deletes order items if their parent order is deleted
);
-- Enable manual insertion of ID values
SET IDENTITY_INSERT Customers ON;
GO
INSERT INTO Customers (CustomerID, FirstName, LastName, Email, RegistrationDate) VALUES
(1, 'John', 'Smith', 'john.smith@email.com', '2024-01-15'),
(2, 'Jane', 'Doe', 'jane.doe@email.com', '2024-02-20'),
(3, 'Peter', 'Jones', 'peter.jones@email.com', '2024-03-10'),
(4, 'Alice', 'Brown', 'alice.brown@email.com', '2024-04-05'),
(5, 'Eve', 'Williams', 'eve.williams@email.com', '2024-05-01'); -- This customer will have no orders
-- Disable manual insertion of ID values
SET IDENTITY_INSERT Customers OFF;
GO
-- Enable manual insertion of ID values
SET IDENTITY_INSERT Orders ON;
GO
INSERT INTO Orders (OrderID, CustomerID, OrderDate, TotalAmount, ShippingAddress) VALUES
-- Orders for John Smith (CustomerID = 1)
(1, 1, '2025-08-10', 149.98, '123 Oak St'),
(2, 1, '2025-09-01', 29.99, '123 Oak St'),
(3, 1, '2025-09-22', 75.00, '123 Oak St'),
-- Orders for Jane Doe (CustomerID = 2)
(4, 2, '2025-07-18', 19.99, '456 Maple Ave'),
(5, 2, '2025-09-15', 350.50, '456 Maple Ave'),
-- Orders for Peter Jones (CustomerID = 3)
(6, 3, '2025-06-05', 45.75, '789 Pine Ln'),
(7, 3, '2025-08-21', 89.99, '789 Pine Ln'),
(8, 3, '2025-09-03', 120.00, '101 Birch Rd'),
(9, 3, '2025-09-11', 55.49, '101 Birch Rd'),
-- Orders for Alice Brown (CustomerID = 4)
(10, 4, '2025-09-23', 0.00, '101 Birch Rd'); -- This order will have no items
-- Disable manual insertion of ID values
SET IDENTITY_INSERT Orders OFF;
GO
-- Enable manual insertion of ID values
SET IDENTITY_INSERT OrderItems ON;
GO
INSERT INTO OrderItems (OrderItemID, OrderID, ProductID, Quantity, UnitPrice) VALUES
-- Items for Order #1
(1, 1, 101, 1, 99.99),
(2, 1, 205, 2, 24.99),
-- Items for Order #2
(3, 2, 310, 1, 29.99),
-- Items for Order #3
(4, 3, 401, 3, 25.00),
-- Items for Order #4
(5, 4, 101, 1, 19.99),
-- Items for Order #5
(6, 5, 502, 1, 299.00),
(7, 5, 205, 2, 25.75),
-- Items for Order #6
(8, 6, 310, 5, 9.15),
-- Items for Order #7
(9, 7, 620, 1, 89.99),
-- Items for Order #8
(10, 8, 101, 2, 40.00),
(11, 8, 401, 1, 40.00),
-- Items for Order #9
(12, 9, 730, 1, 55.49),
-- Add more items to meet the 20-line requirement
(13, 1, 310, 1, 0.00), -- Free item
(14, 4, 205, 2, 0.00), -- Promo
(15, 5, 730, 1, 0.00), -- Included accessory
(16, 6, 101, 1, 0.00), -- Bonus
(17, 7, 401, 4, 0.00), -- Sample
(18, 8, 502, 1, 0.00), -- Gift
(19, 9, 620, 2, 0.00), -- Giveaway
(20, 2, 401, 1, 0.00); -- Extra part
-- Disable manual insertion of ID values
SET IDENTITY_INSERT OrderItems OFF;
GO
UPDATE o
SET
o.TotalAmount = ISNULL(oi.CalculatedTotal, 0)
FROM
Orders AS o
LEFT JOIN (
SELECT
OrderID,
SUM(Quantity * UnitPrice) AS CalculatedTotal
FROM
OrderItems
GROUP BY
OrderID
) AS oi ON o.OrderID = oi.OrderID;
GO
גילוי נאות: הפוסט הזה הוא שלי, אבל את הקודים הנ"ל יצרתי בעזרת ה-AI (במקרה זה - Gemini), והשארתי את העדויות המרשיעות בפנים (התייחסות של הכלי לפרומט שלי...). חוסך המון עבודה שחורה, עבד תקין מהריצה הראשונה, והכנסתי מספר שינויים מינוריים - לא יותר.
אם ננסה להציג את כל המידע שבטבלאות בפקודה אחת, נקבל משהו כזה:
Select *
From Customers C
Inner Join Orders O
On C.CustomerID=O.CustomerID
Inner Join OrderItems I
On O.OrderID=I.OrderID
Order By C.CustomerID,
O.OrderID,
I.OrderItemID;

כבר אפשר לשים לב ששני לקוחות נעלמו: 4 & 5. לקוח 5 נעלם כי אין לו הזמנות ולכן ה-Inner Join פילטר אותו, ואילו ללקוח 4 יש הזמנה (10) אלא שאין לה פריטים.
כדי לא לאבד מידע אפשר להשתמש ב-Left Join בשני המקרים ואזי:
Select *
From Customers C
Left Join Orders O
On C.CustomerID=O.CustomerID
Left Join OrderItems I
On O.OrderID=I.OrderID
Order By C.CustomerID,
O.OrderID,
I.OrderItemID;

עכשיו ניתן לראות גם את לקוח 4 עם הזמנה 10 נטולת הפריטים, וגם את לקוח 5 ללא ההזמנות.
עכשיו הגיעה הודעה בהולה מהמכירות שהם רוצים לקבל דוח עם כל הלקוחות (גם אם אין להם הזמנות), אבל להתעלם מהזמנות ללא שורות. כלומר- להציג גם את לקוח 4 וגם את לקוח 5, אבל ללא הזמנות: את לקוח 5 כי אין לו הזמנות, ואת לקוח 4 כי הזמנה ריקה אינה נחשבת להזמנה.
התשובה האינטואיטיבית והשגוייה היא בערך כך:
Select *
From Customers C
Left Join Orders O
On C.CustomerID=O.CustomerID
Inner Join OrderItems I
On O.OrderID=I.OrderID
Order By C.CustomerID,
O.OrderID,
I.OrderItemID;
במקרה זה נקבל את אותו פלט כמו בשאילתה הראשונה עם שני ה-Inner Join, כי השני "לא מתחשב" ב-Left Join שלפניו, ומפלטר את כל מי שאין לו הזמנה. מה עושים?
אפשרות אחת היא לשנות את הסדר, קודם כל ה-Inner Join ורק אחרי זה ה-Left Join, וכממתבקש מכך - להשתמש ב-Right Join:
Select C.*,O.*,I.*
From OrderItems I
Inner Join Orders O
On O.OrderID=I.OrderID
Right Join Customers C
On C.CustomerID=O.CustomerID
Order By C.CustomerID,
O.OrderID,
I.OrderItemID;

כל הלקוחות בפנים, כולל 4 & 5 שמופיעים ללא הזמנות.
אפשרות שנייה היא להשתמש בסוגריים וליצור Subquery שיתבצע קודם:
Select *
From Customers C
Left Join (Select O.*,
I.OrderItemID,
I.ProductID,
I.Quantity,
I.UnitPrice
From Orders O
Inner Join OrderItems I
On O.OrderID=I.OrderID) OI
On C.CustomerID=OI.CustomerID
Order By C.CustomerID,
OI.OrderID,
OI.OrderItemID;
אינני מצרף צילום מסך - הפלט הוא כמו בשאילתה הקודמת.
האפשרות השלישית שהיא הכי אלגנטית ומפתיעה מעט בניסוח שלה:
Select *
From Customers C
Left Join Orders O
Inner Join OrderItems I
On O.OrderID=I.OrderID
On C.CustomerID=O.CustomerID
Order By C.CustomerID,
O.OrderID,
I.OrderItemID;
העברנו את פסוקית (clause) ה-On הראשונה לסוף (זו של ה-Left Join) וכך הוא מתבצע לאחר ה-Inner Join !
כפי שאפשר לראות - לאחר ה-Left join אין פסוקית On ולאחר ה-Inner Join יש שתיים.
הפלט כמו בשתי השאילתות הקודמות. לגזור ולשמור!




Dive into SoFlo Wheelie Life, the fan-made Scratch game redefining online stunts. Balance your bike, ride steady, and score big as you perform the longest wheelie possible. With smooth physics and easy controls, it’s an addicting challenge for players of all skill levels.
Getting help with writing tasks is not a new thing. Students prefer professional assistance for their academic assignments. Finding the best experts who can provide excellent Assignment Help might be difficult for students. Connect with nz.greatassignmenthelp.com for your academic assignment. This reputed and reliable service provides a wide variety of support and features for writing tasks. Whether you are struggling with complex topics or meeting tight deadlines, the service is ready to assist students with any type of writing needs. They provide invaluable support in research, writing, and creating quality solutions with accuracy and originality in academic assignments. The experts in this service are able to work fast on writing tasks. They provide timely delivery and tailored solutions for your…
Managing coursework alongside other responsibilities can be challenging. Professional coursework help are designed to provide expert support, ensuring high-quality, well-researched, and plagiarism-free content tailored to your academic requirements. Get the help you need to excel in your studies!
Seeking computer science assignment help provides students with expert guidance in complex coding, algorithms, and data structures. It boosts confidence, ensures timely submission, and deepens understanding of critical programming principles for academic success.
Enter the disturbing world of Human Expenditure Program, a psychological horror experience that replaces jump scares with emotional tension and moral reflection.
Continuous updates and the availability of services like LPC (Land Possession Certificate) application showcase the evolving utility of the Bihar Bhumi Jankari system.