Language

Add APPLY to Your TSQL Tool Belt

John Sonmez · Sep 21, 2011 · 4 min read

Every once in a while I stumble across some SQL keyword that I didn’t really know about, but is extremely useful.\n\nThe other day I came across APPLY, or rather CROSS APPLY.\n\nAfter reading through documentation on how it works and articles about it, I had a bit of trouble understanding it because I couldn’t really find a simple explanation.\n\ncriss-cross_1256682\n\nI am going to try to explain it as simply as possible so you can start using it right away.\n\n

How CROSS APPLY works

\n\nThe basic idea behind CROSS APPLY is to allow you to join two sets of data together.\n\nIf you understand how INNER JOIN works, you already understand CROSS APPLY.\n\nThe only difference is CROSS APPLY also allows you to join in a set of data in which that set of data is created or dependent on each row in the first set.\n\nSo basically what that means is that for a normal join you would, for example, join two tables that shared a common key.\n\nI could join my customer table to my orders table to see all the orders for a particular customer like so:\n\n

\n\n\n\n

\n\nNotice how the join is operating on a key that exists independently in each table.\n\nWe could rewrite this to be exactly the same using the CROSS APPLY syntax instead like so:\n\n

\n\n\n\n

\n\nWe can prove these results sets are exactly the same by using EXCEPT to make sure there are no rows in one set that aren’t in the other and then flipping it, like so:\n\n

\n\n\n\n

\n\nJust run this exact query again swapping the SQL above the EXCEPT with the SQL below and make sure it has no results as well.  If both of those queries have no results, then you know the results from each query are the same since EXCEPT will show any results that are in the top query but not in the bottom one.\n\n

So when is CROSS APPLY useful?

\n\nRemember how I said it can do more than a simple join?  Joins are restricted to only joining two sets of data that could be queries independently of each other.\n\nWhat if I said give me the three most recent orders for each customer?\n\nTake a minute and think about how you would write that query.  Go ahead and try to do it.  I’ll wait.\n\nThere are a few ways to do it without using CROSS APPLY, but none of them are really very easy or perform very well.\n\nUsing CROSS APPLY it is simple though:\n\n

\n\n\n\n

\n\nSo CROSS APPLY is useful whenever you have some data that you would want to be able to join against, but are forced to do some kind of sub-query instead because the data you are trying to join is not going to map well against a single key.\n\nThe other instance in which CROSS APPLY will be useful is when you are  doing a sub-select that has more than one value you would like to use in your final query.\n\nFor example if you were sub-selecting from an Order Details table to match up order ids that had a Quantity greater than 5, that sub-select would need to return exactly one column in order for you to use it in your where clause.  If you wanted to use other columns from the sub-select, you would have to do another sub-select for each of these columns.\n\nIf you first try to rewrite the sub-select as a JOIN and find that you can’t, you may be able to write it as a CROSS APPLY.\n\n

How to know when to use CROSS APPLY

\n\nThere isn’t a good solid rule you can use to identify when you should use a CROSS APPLY but having the knowledge of CROSS APPLY and how it works can help you when you are trying to tune queries and you are having a difficult time constructing one.  It is another option you can try.\n\nHere are some general guidelines of times when you might want to use CROSS APPLY:\n\n

    \n

  • A query where the result set you want to JOIN against is in some way related to the data in the first set.  (Example: one column in the first table tells you how many rows in the 2nd table to get)
  • \n

  • A query where you are doing a sub-query, but need more than one value from the sub-query
  • \n

  • Anywhere you are using a Common Table Expression (CTE) could possibly be rewritten as a CROSS APPLY
  • \n

  • A query that has a large set of data it is joining against and then filtering out.  You can change it to a CROSS APPLY that does the filter in the CROSS APPLY statement.
  • \n

  • Any time you are trying to join against a table function (this is actually what CROSS APPLY was created for.)
  • \n

John Sonmez

John Sonmez

John Sonmez is the founder of Simple Programmer, author of "The Complete Software Developer's Career Guide" and "Soft Skills: The Software Developer's Life Manual." He helps software developers build remarkable careers.