简体   繁体   中英

MySQL: Select Category and (optional) Sub-Category for Projects in One Statement

In my MySQL-Database, I have two tables, one for the projects and one for the categories:

The projects-table looks something like this:

 id | project_title        | category_id
 ---|----------------------|------------
  1 | My Book Project      | 101
  2 | My Comic Project     | 102
  3 | My Magazine Project  | 104

Then I have the categories. These can have a parent category which is stored in the same table:

 id | category_title     | parent_id  
 ---|--------------------|----------
101 | Books              | 0
102 | Comics             | 101
103 | DVDs               | 0
104 | Magazines          | 101

I like to fetch all the projects with the according category and (optional) sub-category (if parent_id is provided). If the category has no sub-category, the sub-category should be something like "-" or "none".

Now I know how I can get all these values with several statements:

First Statement: Fetch the projects with the indicated category (which can be a main-category or a sub category, therefor I fetch also the category's parent_id ):

SELECT
    p.project_title, 
    c.category_title,
    c.parent_id as cat_parent_id
FROM
    projects p, 
    categories c
WHERE
    p.category_id = c.id

Second Statement(s): After that, I could fetch the possible sub-category of a project within a loop, or assign the found category as main-category, eg with php:

<?php
foreach( $rows as $project ) {
    if ( $project['cat_parent_id'] > 0 ) {
        $project['sub_category'] = $project['category_title'];
        // query main-category here
    }
    else {
        $project['main_category'] = $project['category_title'];
        $project['sub_category'] = 'none';
    }

    // do things with this project ...
}
?>

The problem is that I will have another query for each project found, and this is not nice. I think there should be a way to fetch all the required values in one statement. I found this question on SO which is nearly the same, but in my case, the sub-category is obtional.

As John Cleese would say: Could someone please give me a push?

You can join categories twice:

SELECT
    p.project_title, 
    c.category_title,
    COALESCE(c0.category_title, '-') 
FROM projects p join categories c on p.category_id = c.id
                left join categories c0 on c.parent_id = c0.id;

But it will work only for two levels hierarchy (any category may have zero or one parent).

Accoding to the comments:

SELECT
    p.project_title, 
    COALESCE(c0.category_title, c.category_title),
    case when c0.id is not null then c.category_title else '-' end
FROM projects p join categories c on p.category_id = c.id
                left join categories c0 on c.parent_id = c0.id;
SELECT
    p.project_title, 
    IF(c2.category_title is null,
       c1.category_title,
       c2.category_title) as main_category,
    IF(c2.category_title is null,
       "none",
       c1.category_title) as sub_category
FROM projects p
LEFT JOIN categories c1 ON (c1.id = p.category_id)
LEFT JOIN categories c2 ON (c2.id = c1.parent_id)

http://sqlfiddle.com/#!2/85020/1

This returns the requested result:

PROJECT_TITLE        MAIN_CATEGORY  SUB_CATEGORY
My Book Project      Books          none
My Comic Project     Books          Comics
My Magazine Project  Books          Magazines

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM