使用单个查询获取类别和文章

时间:2014-09-30 20:41:36

标签: php mysql sql pdo

我有两个SQL表:

  1. 类别:id,title,level,parent
  2. 文章:id,title,category_id
  3. 现在我想得到这个结果:

    Category 1
        Article 1
        Artcile 2
        Article 3
    Category 2
        Subcategory 1
            Article 1
            Artcile 2
            Article 3
        Subcategory 2
            Article 1
            Artcile 2
            Article 3
    Category 3
        Article 1
        Artcile 2
        Article 3
    

    我会这样做:

    $categories = $db->prepare('SELECT * FROM categories WHERE level = 0');
    $categories->execute();
    while($category = $categories->fetch(PDO::FETCH_OBJ)) {
        $sub_categories = $db->prepare('SELECT * FROM categories WHERE parent = :parent_id');
        $sub_categories->bindParam(':parent_id', $category->id, PDO::PARAM_INT);
        $sub_categories->execute();
        while($sub_category = $sub_categories->fetch(PDO::FETCH_OBJ)) {
            $articles = $db->prepare('SELECT * FROM articles WHERE category_id = :category_id');
            $articles->bindParam(':category_id', $sub_category->id, PDO::PARAM_INT);
            $articles->execute();
            while($article = $articles->fetch(PDO::FETCH_OBJ)) {
                echo $article->title.'<br />';
            }
        }
    
    }
    

    首先,这是非常糟糕的,因为它只是从子类别(不是类别)获取文章,只有一个级别的选择。

    第二:我使用三个查询,这些查询被多次执行,只是为了那个基本的东西。表现......: - (

    我想用一个SQL查询来解决这个问题。这可能吗? (然后我会创建输出......)

    SQLfiddle: http://sqlfiddle.com/#!2/2a4f2

1 个答案:

答案 0 :(得分:0)

你可以试试这句话:

SELECT
    A.id, A.title,
    C.id AS category_id, C.title AS category_title, C.level AS category_level,
    P.id AS parent_id, P.title AS parent_title, P.level AS parent_level
FROM articles AS A
    INNER JOIN categories AS C ON A.category_id=C.id
    LEFT JOIN categories AS P ON C.parent=P.id

这将为您提供所有文章,包括主要类别和(可选)父类别。但您必须考虑,该类别可以是主要类别或子类别。

您可以通过这种方式更改它,以便始终直接获取主要和子类别并对其进行排序。

SELECT
    IFNULL(P.id, C.id) AS category_id, IFNULL(P.title, C.title) AS category_title,
    IF(P.id IS NULL, NULL, C.id) AS subcategory_id, IF(P.title IS NULL, NULL, C.title) AS subcategory_title,
    A.id, A.title
FROM articles AS A
    INNER JOIN categories AS C ON A.category_id=C.id
    LEFT JOIN categories AS P ON C.parent=P.id
ORDER BY category_id, subcategory_id, A.id

IFNULL查看是否存在父类别。如果是,则父P是主要类别;如果没有,则类别C是主要的。下一行检查是父PNULL。如果是,则没有子类别;如果不是,则类别C是子类别。看起来有点不方便,但是对于两个级别它可以正常工作:

http://sqlfiddle.com/#!2/0ed4d/4