2014-11-20 86 views
2

在我的MySQL数据库,我有两个表,一个项目,一个用于类别:MySQL的:选择类别和在一条语句(可选)子类别的项目

的项目表看起来是像这样:

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

然后我有类别。这些可以具有被存储在同一表中的父类别:

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

我喜欢获取所有与根据类别和(可选)子类别的项目(如果提供parent_id)。如果该类别没有子类别,则子类别应该是“ - ”或“none”。

现在我知道我能得到所有这些值与几个语句:

首先声明:获取与指示类别的项目(可以是主类别或子类别,为此我取也类别的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 

第二条语句(S:在那之后,我可以在一个循环中获取一个项目的可能的子类,或者给发现类别作为主要类别,如用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 ... 
} 
?> 

问题是,我会找到的每个项目中的另一个查询,这是不是很好。我认为应该有办法在一个语句中获取所有必需的值。我发现SO上的this question几乎相同,但在我的情况下,子类别是obtional。

正如John Cleese所说:有人能给我一个推动力吗?

+0

我不明白什么是PARENT_ID!?!? – Strawberry 2014-11-20 16:50:25

+0

parent_id是同一个表中父类别的标识。但并非所有类别都有子类别。在该项目中,所选类别(主或子)的ID被保存。我想得到两个值,或者 - 如果没有指定子类别 - 短划线(或“无”) – uruk 2014-11-20 16:53:42

+0

好的。请注意,按照惯例,NULL通常用于识别孤儿。 – Strawberry 2014-11-20 16:55:47

回答

4

您可以参加两次类别:

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; 

但它会工作只为两个级别的层次结构(任何类别可能有零或一个父)。

Accoding的评论:

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; 
+0

差不多!如果指定了子类别,则将其输出为主类别,将主类别输出为子类别。当没有parent_id可用时,您的代码按预期工作。 – uruk 2014-11-20 16:58:41

+0

@uruk你想改变列的位置?项目 - 亲子? – Multisync 2014-11-20 17:02:12

+0

是的,但仅限于,如果存在子类别。 – uruk 2014-11-20 17:04:24

0
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

这将返回请求的结果:

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

谢谢。这也工作得很好。两种解决方案的速度似乎都是相同的。 – uruk 2014-11-20 17:59:15