【问题标题】:Get categories and articles with a single query通过单个查询获取类别和文章
【发布时间】:2014-09-30 20:41:35
【问题描述】:

我有两个 SQL 表:

  1. 类别:id、title、level、parent
  2. 文章:id、title、category_id

现在我想得到这个结果:

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

【问题讨论】:

  • 你想要什么输出?
  • @JayBlanchard 我渴望名利!
  • 只需要上面显示的结果。这意味着类别的标题和文章的标题......
  • 你想输出名利@Charles? ¯_(ツ)_/¯
  • 我们需要查看您的表架构。你能设置一个 SQL 小提琴吗? sqlfiddle.com

标签: php mysql sql pdo


【解决方案1】:

你可以试试这个说法:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多