首页 > 解决方案 > Mysql子猫和父猫的帖子[数据库模式]

问题描述

好的,所以我有一个简单的类别表和一个单独的帖子表很容易,但是当用户发布帖子时,我认为我应该将子猫和父猫都存储在帖子表中,但这不会是很多数据重复,所以我而是只存储 sub_cat 然后我使用一些 PHP 函数来查询数据库中的主猫及其名称。

类别表

ID | cat_name | main_cat
1  | Dinner   | 0 
2  | Chicken  | 1  

帖子表

ID | title | sub_cat | fields that are not related to Q
1  | test  | 2       | 
 

Get parent(main) category $sub_cat = 来自获取帖子及其 sub_cats 的选择查询

function main_cat($sub_cat){
    require("conn_posts.php");
    $stmt = $conn_posts->prepare("SELECT `main_cat` FROM `cats` WHERE `ID` = ?");
    $stmt->bind_param("s", $sub_cat);
    $stmt->execute();
    $stmt_results = $stmt->get_result(); // get result

    while($row_get = $stmt_results->fetch_assoc()){
        if($row_get['main_cat'] == 0){
            return $sub_cat;
        }elseif($row_get['main_cat'] !== ""){
            return $row_get['main_cat'];
        }
    }
}

只要 id 有效,此函数就可以获取任何类别名称

function cat_name($cat_number){
    require("conn_posts.php");
    $stmt = $conn_posts->prepare("SELECT `cat_name` FROM `cats` WHERE `ID` = ?");
    $stmt->bind_param("s", $cat_number);
    $stmt->execute();
    $stmt_results = $stmt->get_result(); // get result
    $row_get = $stmt_results->fetch_assoc(); 

    if($stmt_results->num_rows <= 0){
        return 0;
    }elseif($stmt_results->num_rows == 1){
        return $row_get['cat_name'];
    }
}

我的问题是这是处理我的帖子子类别和父类别的好方法有没有更好的方法来做我目前正在做的事情?例如。我的数据库架构好吗(我的意思是在帖子表中包含父猫 ID 比进行 PHP 服务器端处理更好)?

标签: phpmysql

解决方案


您的数据库架构很好:它不包含任何复制,我不会更改它。但是,您在 PHP 中处理获取类别的方式并不是真正的最佳选择:您几乎应该始终致力于最大限度地减少查询数量,因为它(通常)会影响性能而不是查询的复杂性。

如果您正在运行 MySQL 8+,那么使用递归 CTE 是一个很好的方法;它将允许您通过一个查询获取所有父母:

WITH RECURSIVE cte AS (
    SELECT id, cat_name, main_cat, 0 as depth FROM categories WHERE ID=3
    UNION ALL
    SELECT categories.id, categories.cat_name, categories.main_cat, cte.depth+1 as depth
    FROM cte inner join categories
    ON cte.main_cat = categories.id
)
SELECT cat_name FROM cte order by depth ASC

该查询中的数字“3”可以替换为您尝试检索的类别。您可以查看此DB fiddle以获取实时示例。如果我看到您的代码,将其合并到您的 PHP 中应该是相当简单的。如果没有,请发表评论,我会尝试扩展。


推荐阅读