wasimbhalli
wasimbhalli

Reputation: 5242

Sql Self join query? How to get categories sub categories?

I've a database table, which has the following form

catID | category      | parentID
1     | firstCategory | null
2     | SubCategory1  | 1
3     | SubCategory2  | 1
4     | subSub1       | 3

and so on...

There are multiple level of categories. What query can be used to get the records in the following format:

catID | category 
1     | firstCategory
2     | firstCategory/SubCategory1
3     | firstCategory/SubCategory2
4     | firstCategory/SubCategory2/subSub1

The category id will be the id of the last category. How to write a query to join the categories to all levels? The exact number of levels for different categories is different?

I'm using mySQL.

Upvotes: 4

Views: 2077

Answers (3)

usr
usr

Reputation: 171178

There is an alternative to what cyberkiwi said: Query the whole table and to the tree building in memory. Imperative languages are well suited for that while SQL is not. The performance will be much better (because SQL has to scan the table not only once but for every level).

Upvotes: 0

Jody
Jody

Reputation: 8291

Oracle has this functionality, and the company I work for uses it for exactly what you are describing. The queries can be quite heavy at times though. A good writeup of the functions ("start with" and "connect by" keywords) is found here at this link, along with pseudo code you might try to wrap your head around...though cyberkiwi's answer is probably just fine for all practical purposes...

http://www.adp-gmbh.ch/ora/sql/connect_by.html

Upvotes: 0

RichardTheKiwi
RichardTheKiwi

Reputation: 107716

For a maximum depth of 6 (including root), you can use this

select l0.catID,
    concat(
      case when l5.catID is null then '' else concat(l5.category, '/') end
    , case when l4.catID is null then '' else concat(l4.category, '/') end
    , case when l3.catID is null then '' else concat(l3.category, '/') end
    , case when l2.catID is null then '' else concat(l2.category, '/') end
    , case when l1.catID is null then '' else concat(l1.category, '/') end
    , l0.category)
from catcat l0
left join catcat l1 on l0.parentID=l1.catID
left join catcat l2 on l1.parentID=l2.catID
left join catcat l3 on l2.parentID=l3.catID
left join catcat l4 on l3.parentID=l4.catID
left join catcat l5 on l4.parentID=l5.catID

Expand the pattern as required for longer max depths.

Upvotes: 2

Related Questions