Recursion eh! I'll bet you're storing hierarchical data here, not just a one-level parent-child relationship.
If it is just one level then the way you are storing the data is ok and the solution is straightforward: you join the table to itself to get the children of any parent, as in my query.
Now, your problem was : "I now need to list all the items in a given category and all of it's sub-categories, then sort them in various orders."
Not clear, but it sounds like items do not have to be in a sub-category, they can just be in the main category itself. Shame, it makes things messy.
The best way to clean that up is to store it's own id in the parent_id field of each parent - make it it's own parent. Then when you join the table to itself, the parent category shows up on both sides of the join along with all the children.
To get an orderly list of cat ids to join to the items table can then do this
$sql = "SELECT s.id, s.title FROM category c INNER JOIN category s
ON c.id=s.parent_id
WHERE c.id = $category_id_to_search";
That will give you the parent category listed once with all the children. You then extend it to the items table thus
$sql = "SELECT s.title,i.* FROM
category c INNER JOIN category s ON c.id=s.parent_id
INNER JOIN items i ON s.id = i.location_id
WHERE c.id = $category_id_to_search";
Unless I've completely missunderstood you, that should return what you want, every item in a cat or it's sub-cats.
Now, if it hierarchical data you are dealing with then just READ THIS