0

I have a taxonomies table like this:

+-----+--------------+----------------+--------------------+
| id  | name         | is_subcategory | parent_taxonomy_id |
+-----+--------------+----------------+--------------------+
|  80 | Headword     |              0 |                  0 |
|  81 | blonde       |              1 |                 80 |
|  82 | Parents      |              0 |                  0 |
|  83 | Children     |              1 |                 82 |
|  84 | Season       |              0 |                  0 |
|  85 | Winter       |              1 |                 84 |
|  86 | Charm Units  |              0 |                  0 |
|  88 | Etymology    |              1 |                 86 |
|  89 | Word History |              1 |                 86 |
|  90 | Spring       |              1 |                 84 |
|  91 | Summer       |              1 |                 84 |
|  93 | Trends       |              0 |                  0 |
| 109 | Interest     |              0 |                  0 |
| 110 | Sports       |              1 |                109 |
| 111 | Cups         |              0 |                  0 |
| 112 | hot          |              1 |                111 |
| 113 | Speakers     |              0 |                  0 |
| 114 | Hi def       |              1 |                113 |
| 115 | Dual powered |              1 |                113 |
| 118 | Office       |              0 |                  0 |
| 124 | States       |              0 |                  0 |
+-----+--------------+----------------+--------------------+

I need to fetch a list of all categories and subcategories from autocomplete, for example, if user types in sp - he should get this list:

Interest/Sports
Season/Spring
Speakers
Speakers/Dual powered
Speakers/Hi def

Am I correct - I should do a self join? How would I get results in such format?

Edit:

here's my query that seems to work:

SELECT a.id AS cat_id, b.id AS subcat_id, a.name AS cat_name, b.name AS sub_cat_name, CONCAT_WS(' / ', a.name, b.name) AS full_name 
FROM taxonomies as a
LEFT JOIN taxonomies AS b ON a.id = b.parent_taxonomy_id
WHERE (a.name LIKE 'sp%' OR b.name LIKE 'sp%')
ORDER BY full_name DESC;
Dannyboy
  • 1,963
  • 3
  • 20
  • 37

2 Answers2

1

Consider the following:

DROP TABLE my_table;

CREATE TABLE my_table
(id  INT NOT NULL PRIMARY KEY
,name         VARCHAR(20) NOT NULL UNIQUE
,parent_taxonomy_id INT NULL
);

INSERT INTO my_table VALUES
( 80,'Headword',NULL),
( 81,'blonde',80),
( 82,'Parents',NULL),
( 83,'Children',82),
( 84,'Season',NULL),
( 85,'Winter',84),
( 86,'Charm Units',NULL),
( 88,'Etymology',86),
( 89,'Word History',86),
( 90,'Spring',84),
( 91,'Summer',84),
( 93,'Trends',NULL),
(109,'Interest',NULL),
(110,'Sports',109),
(111,'Cups',NULL),
(112,'hot',111),
(113,'Speakers',NULL),
(114,'Hi def',113),
(115,'Dual powered',113),
(118,'Office',NULL),
(124,'States',NULL);

SELECT n.*
  FROM 
     ( SELECT x.id x_id
            , x.name x_name
            , y.id y_id
            , y.name y_name
         FROM my_table x 
         LEFT 
         JOIN my_table y 
           ON y.parent_taxonomy_id = x.id 
        WHERE x.parent_taxonomy_id IS NULL
     ) n 
 WHERE (x_name LIKE 'sp%' OR y_name LIKE 'sp%');

+------+----------+------+--------------+
| x_id | x_name   | y_id | y_name       |
+------+----------+------+--------------+
|   84 | Season   |   90 | Spring       |
|  109 | Interest |  110 | Sports       |
|  113 | Speakers |  114 | Hi def       |
|  113 | Speakers |  115 | Dual powered |
+------+----------+------+--------------+
Strawberry
  • 33,750
  • 13
  • 40
  • 57
0

A speed up of the process could be done by reducing the number of results fetched and storing the taxonomy path:

+-----+--------------+----------------+--------------------+--------+
| id  | name         | is_subcategory | parent_taxonomy_id | path   |
+-----+--------------+----------------+--------------------+--------+
|  80 | Headword     |              0 |                  0 | 0      |
|  81 | blonde       |              1 |                 80 | 80/0   |
|  82 | Parents      |              0 |                 81 | 81/80/0|

The search for Pa would get you as response:

|  82 | Parents      |              0 |                 81 | 81/80/0|

But instead of now recursive joining on parent_taxonomy_id you would execute a query searching for records 80,81 and 0, which are quick key lookups.

Key to this is that you do not fetch all the possible categories (so limit the user to 5-10 top options for example) since that would lead to too many key lookups (even if you would optimize the lookups by de-duplicating them first).

In ajax style this works really well:

You can present the results of the first query immediate:

../Parents

Then delayed replace the ../ with the path:

0/Headword/blonde/parent

(record 0 was not in your data, you can define 0 yourself of course :) )

Norbert
  • 6,026
  • 3
  • 17
  • 40