JOINs combine rows from two or more tables based on a related column.
JOINs let the optimizer combine tables before filtering, often running faster and keeping code readable. Subqueries materialize intermediate results that can slow performance in large datasets.
SQL Server offers INNER, LEFT OUTER, RIGHT OUTER, FULL OUTER, CROSS, and SELF JOINs. Each dictates how unmatched rows are handled when combining tables.
Use INNER JOIN when you only need rows with matching keys in both tables. It is the default JOIN type when you omit the word INNER.
SELECT c.name, o.total_amount
FROM Customers AS c
INNER JOIN Orders AS o
ON o.customer_id = c.id;
Use OUTER JOINs. LEFT returns all rows from the first (left) table, filling NULLs for non-matches. RIGHT does the opposite; FULL returns rows from both sides.
-- Customers without orders
SELECT c.name, o.id AS order_id
FROM Customers AS c
LEFT JOIN Orders AS o
ON o.customer_id = c.id;
CROSS JOIN creates a cartesian product. Use it for generating test data or pairing every customer with every product only when necessary, as row counts multiply quickly.
1) Index foreign keys such as Orders.customer_id. 2) Always qualify column names to avoid ambiguity. 3) Filter early with ON, not WHERE, to minimize result size.
Chain JOIN clauses. SQL Server evaluates them left to right, applying ON conditions at each step.
SELECT c.name, p.name AS product, oi.quantity
FROM Customers AS c
JOIN Orders AS o ON o.customer_id = c.id
JOIN OrderItems AS oi ON oi.order_id = o.id
JOIN Products AS p ON p.id = oi.product_id;
Check ON conditions for wrong columns, verify data types match, and temporarily switch to FULL JOIN to see unmatched rows quickly.
Yes. Combine conditions with AND inside the ON clause: ON a.col1 = b.col1 AND a.col2 = b.col2
.
No. Writing FROM A, B WHERE A.id = B.id
is functionally an INNER JOIN, but explicit JOIN syntax is clearer and easier to maintain.
GROUP BY the primary key columns and use HAVING COUNT(*) > 1 to surface duplicates created by one-to-many relationships.