APPLY is one of SQL Server's most useful advanced operators when the right-side logic must run in the context of each row from the left.
Complete 12 of 24 practices (50%) and enter your name to unlock the Certificate of Participation.
Traditional joins work beautifully when both sides can be related with a normal join predicate. APPLY becomes valuable when the right side must reference columns from the current row on the left.
Imagine asking a different question for each customer: 'What is this customer's latest order?' The right-side query needs that customer's ID before it can answer.
SELECT c.CustomerID, x.*
FROM dbo.Customers AS c
CROSS APPLY
(
-- This query can use c.CustomerID
SELECT ...
) AS x;
APPLY is best understood as: take one left row, run a table expression that can see that row, then combine the results.
CROSS APPLY returns a left row only when the right-side expression returns at least one row. That makes it ideal when 'no related result' should mean 'exclude this left row.'
If a customer has no qualifying order, CROSS APPLY does not produce a row for that customer.
SELECT c.CustomerID,
x.OrderID,
x.OrderDate
FROM dbo.Customers AS c
CROSS APPLY
(
SELECT TOP (1)
o.OrderID,
o.OrderDate
FROM dbo.Orders AS o
WHERE o.CustomerID = c.CustomerID
ORDER BY o.OrderDate DESC, o.OrderID DESC
) AS x;
CROSS APPLY is a strong choice when a missing right-side result should remove the left entity from the answer.
OUTER APPLY uses the same row-dependent idea as CROSS APPLY, but it preserves the left row when the right side returns nothing. The missing right-side columns become NULL.
A customer with no orders still appears in the report. OrderID and OrderDate are simply NULL.
SELECT c.CustomerID,
x.OrderID,
x.OrderDate
FROM dbo.Customers AS c
OUTER APPLY
(
SELECT TOP (1)
o.OrderID,
o.OrderDate
FROM dbo.Orders AS o
WHERE o.CustomerID = c.CustomerID
ORDER BY o.OrderDate DESC, o.OrderID DESC
) AS x;
The CROSS vs OUTER decision is fundamentally a business rule: should left rows with no right-side result disappear or remain?
One of APPLY's strongest production patterns is asking a different Top-N question for every left-side entity: latest order per customer, newest status per employee, top three transactions per account, or highest-priority event per device.
For Customer 101, find Customer 101's latest order. For Customer 102, run the same logic using Customer 102's key. APPLY expresses that relationship directly.
SELECT e.EmployeeID,
s.StatusCode,
s.EffectiveDate
FROM dbo.Employee AS e
OUTER APPLY
(
SELECT TOP (1)
h.StatusCode,
h.EffectiveDate
FROM dbo.EmployeeStatusHistory AS h
WHERE h.EmployeeID = e.EmployeeID
ORDER BY h.EffectiveDate DESC,
h.StatusHistoryID DESC
) AS s;
APPLY makes 'latest related row per entity' readable because the correlation and ranking logic stay together.
APPLY is not limited to subqueries. VALUES can create a small row expression that calculates a value once, gives it a name and lets the rest of the query reuse it.
Instead of repeating Revenue - Cost in several CASE expressions and output columns, define GrossProfit once and reuse the alias.
SELECT s.SaleID,
x.GrossProfit,
CASE WHEN x.GrossProfit > 0
THEN 'Profit'
ELSE 'Loss'
END AS ProfitFlag
FROM dbo.Sales AS s
CROSS APPLY
(
VALUES (s.Revenue - s.Cost)
) AS x(GrossProfit);
APPLY can act as a readability tool, not just a join-like operator.
A table-valued function can behave like a parameterized table. APPLY lets each left row feed its own values into that function and receive a rowset back.
For each employee, call a function that returns that employee's qualifying assignments. The left row supplies EmployeeID; the function returns rows.
SELECT e.EmployeeID,
a.AssignmentID,
a.Hours
FROM dbo.Employee AS e
CROSS APPLY dbo.fn_OpenAssignments(e.EmployeeID) AS a;
APPLY is the natural bridge when a reusable table expression needs parameters from each row.
APPLY can be elegant and fast, but syntax alone tells you nothing about cost. A row-dependent lookup may run efficiently with the right index—or become expensive when repeated for a large left input.
If 500,000 left rows each trigger a poorly supported lookup, a clean-looking query can still be expensive.
CREATE INDEX IX_Orders_Customer_Date
ON dbo.Orders
(
CustomerID,
OrderDate DESC,
OrderID DESC
)
INCLUDE (Amount, Status);
Use APPLY because it expresses the problem well, then verify that the optimizer can execute that expression efficiently.
APPLY is a tool, not a badge of sophistication. A standard JOIN may be simpler for ordinary relationships. A window function may be better for set-wide ranking. APPLY is strongest when the right-side table expression naturally depends on the current left row.
The best SQL is not the query with the most advanced keyword. It is the query whose logic is easiest to understand, validate and operate at the required scale.
Need right-side logic
that depends on each left row?
|
YES
|
APPLY candidate
/ \
CROSS OUTER
drop no-match keep no-match
Otherwise:
consider JOIN or window functions.
The production mindset is simple: use APPLY where it clarifies row-dependent logic, not merely because you can.
Open each item after answering it in your own words. The 24 interactive practices above drive certificate progress.
The right-side table expression can reference columns from the current row on the left.
CROSS APPLY drops a left row when the right side returns nothing; OUTER APPLY keeps it and returns NULLs on the right.
To select the latest, best or highest-priority related row separately for each left-side entity.
Row-dependent work can be repeated for many left rows, so indexes, cardinality, logical reads and the actual plan matter.
When a normal JOIN or a set-based window-function solution expresses the problem more simply and performs appropriately.
| Need | Strong candidate |
|---|---|
| Right-side logic depends on each left row | APPLY |
| Exclude left rows with no right-side result | CROSS APPLY |
| Keep all left rows even with no right-side result | OUTER APPLY |
| Latest or Top-N related rows per entity | APPLY + TOP + ORDER BY |
| Ordinary relationship between two sets | JOIN |
Complete at least 12 of the 24 practice cases (50%) and enter your name.
APPLY is most valuable when the right-side table expression truly depends on each left row.