3

I've two MS SQL tables: Category, Question. Each Question is assigned to exactly one Category. One Category may have many subcategories.

Category

  • Id : bigint (PK)
  • Name : nvarchar(255)
  • AcceptQuestions : bit
  • IdParent : bigint (FK)

Question

  • Id : bigint (PK)
  • Title : nvarchar(255) ...
  • IdCategory : bigint (FK)

How do I recursively count all Questions for a given Category (including questions in subcategories). I've tried it already based on several tutorials but still can't figure it out :(

1
  • Thomas, SQL SERVER 2008 Express Edition. Commented May 19, 2010 at 16:52

1 Answer 1

10
with /* recursive */ category_tree as (
  select category.id as top_category_id, category.id as category_id
  from category
union all
  select top_category_id, category.id
  from category_tree
       join category on category.idparent = category_tree.category_id
)
select category_tree.top_category_id as category, count(*) as question_count
from category_tree
     join question on question.idcategory = category_tree.category_id
group by category_tree.top_category_id

The CTE builds a list of which subcategories are under each category- essentially, it recurses through the tree and produces a flattened view of (top category, descendant category).

The initial term (before the union all) selects each category, and indicates that it contains itself- the recursive term then includes all the subcategories for categories found so far, and stops (produces no results) automatically when all the category_id columns in the previous iteration were leaf categories.

Based on that, we simply join this flattened view back onto question to produce a set of (top category, question) rows, and aggregate based on (top category).

Sign up to request clarification or add additional context in comments.

2 Comments

araqnid, your solution works right out of the box, however the result set contains all categories. How to get the count just for a given category id?
add a "where" clause to the initial term inside the definition of category_tree, just before the "union all". That defines the start point for scanning the category tree- if you restrict it to a single category, you'll get the subtree rooted at that category.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.