top of page

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

אני מניח שכל מי שקורא את הפוסט יודע מה ההבדל בין Inner Join ל-Left Join, והכוונה שלי היא לטפל במקרה יותר מורכב. נניח שיש לנו 3 טבלאות:

  1. Customers

  2. Orders

  3. 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;

ree

כבר אפשר לשים לב ששני לקוחות נעלמו: 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;

ree

עכשיו ניתן לראות גם את לקוח 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;

ree

כל הלקוחות בפנים, כולל 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 יש שתיים.

הפלט כמו בשתי השאילתות הקודמות. לגזור ולשמור!












9 Comments


SULLY
Nov 03

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.

Like

Jack Owen
Nov 01

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…

Like

Kia Moore
Oct 29

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.

Edited
Like

nicky
Oct 23

Enter the disturbing world of Human Expenditure Program, a psychological horror experience that replaces jump scares with emotional tension and moral reflection.

Like

Guest
Oct 22

Continuous updates and the availability of services like LPC (Land Possession Certificate) application showcase the evolving utility of the Bihar Bhumi Jankari system.


Like

STAY IN TOUCH

Get New posts delivered straight to your inbox

Thank you for subscribing!

bottom of page