Mysql 如何将一个表连接到产品和类别树应用程序中的一个表(两个不同的表作为一个表)?

Mysql 如何将一个表连接到产品和类别树应用程序中的一个表(两个不同的表作为一个表)?,mysql,sql,Mysql,Sql,我正在制作一个产品和类别树。树接受产品存在于任何类别中,无论是父节点还是叶子 这是我的桌子 #category table +------+-----------+-------------+ | ID | cat_name | parent_cat | +------+-----------+-------------+ | 1 | TV | NULL | +------+-----------+-------------+ | 2 | L

我正在制作一个产品和类别树。树接受产品存在于任何类别中,无论是父节点还是叶子

这是我的桌子

#category table
+------+-----------+-------------+
|  ID  |  cat_name | parent_cat  |
+------+-----------+-------------+
|   1  |     TV    |     NULL    |
+------+-----------+-------------+
|   2  |    LCD    |      1      |
+------+-----------+-------------+
|   3  |   PLASMA  |      1      |
+------+-----------+-------------+


#product table
+------+-----------+-----------+
|  ID  |  prd_name |  prd_cat  |
+------+-----------+-----------+
|   1  |     LG    |     1     |
+------+-----------+-----------+
|   2  |     HD    |     2     |
+------+-----------+-----------+
|   3  |    FHD    |     2     |
+------+-----------+-----------+
我想要做的是做一个select查询来检索包含所有类别和产品的完整树

我可以通过此查询检索类别

select cat1.cat_name lvl1, cat2.cat_name lvl2
from category cat1 left join category cat2 on cat1.ID = cat2.parent_cat
where cat1.parent_cat is null;
select cat1.cat_name,cat2.cat_name,product.prd_name
from category cat1 left join category cat2 on cat1.ID = cat2.parent_cat
left join product on cat1.ID = product.prd_cat
where cat1.parent_cat is null;
这给了我类似的东西

+------+------+
| lvl1 | lvl2 |
+------+------+
|  TV  |  LCD |
+------+------+
|  TV  |PLASMA|
+------+------+
当我尝试在树中加入产品时,我使用了这个查询

select cat1.cat_name lvl1, cat2.cat_name lvl2
from category cat1 left join category cat2 on cat1.ID = cat2.parent_cat
where cat1.parent_cat is null;
select cat1.cat_name,cat2.cat_name,product.prd_name
from category cat1 left join category cat2 on cat1.ID = cat2.parent_cat
left join product on cat1.ID = product.prd_cat
where cat1.parent_cat is null;
但是sql给了我这个结果

+-----------+-----------+-----------+
|  cat_name |  cat_name |  prd_name |
+-----------+-----------+-----------+
|    TV     |    LCD    |     LG    |
+-----------+-----------+-----------+
|    TV     |   PLASMA  |     LG    |
+-----------+-----------+-----------+
我希望product表被视为category(level 2)表,因此,如果像TV这样的父节点有一些子类别和子产品,我会同时获得它们如何获得这样的结果树:

+-------------+------------+------------+
| tree_lvl_1  | tree_lvl_2 | tree_lvl_3 |
+-------------+------------+------------+
|      TV     |     LG     |    NULL    |
+-------------+------------+------------+
|      TV     |     LCD    |     HD     |
+-------------+------------+------------+
|      TV     |     LCD    |     FHD    |
+-------------+------------+------------+
|      TV     |   PLASMA   |    NULL    |
+-------------+------------+------------+
电视(类别)>LG(产品)

电视(类别)>LCD(类别)>HD(产品)

电视(类别)>LCD(类别)>FHD(产品)

电视(类别)>等离子(类别)



编辑:你建议的是建立一个只包含类别的树,我知道怎么做。我这里的问题是我还有一个“products”表,它应该像category一样作为一个节点加入到树中!我希望将类别表和产品表视为一个表(节点)

会计师,这里的不是一个不平衡的层次结构(层次结构树的各个分支具有不同的长度),而是一个参差不齐的层次结构

当你有一个固定的最低级别(产品,在你的情况下)和一个不平衡的层次结构(类别,在你的情况下)时,层次结构是参差不齐的

因此,理论上:

cat_l1|cat_l2|prd
TV    |NULL  |LG
TV    |LCD   |HD
TV    |LCD   |FHD
TV    |PLASMA|NULL
我的答案基于设计和填充包含这种层次结构的维度表的事实标准。 最低级别是主键级别,因此它是产品。经典的表格设计将主键放在第一位。然后,我继续按列中预期基数的顺序-向下分层

填充参差不齐层次结构中的漏洞是通过人工平衡除最低层之外的所有层来实现的:您向下复制父层,直到所有层都被填充

您没有用于PLASMA子类别的产品。使用此设计,您要么不为该子类别创建任何行,要么创建一个“不适用”的产品条目,例如,带有负ID。如下所示:

cat_l1|cat_l2|prd
TV    |TV    |LG
TV    |LCD   |HD
TV    |LCD   |FHD
TV    |PLASMA|not applicable
下面的脚本抑制了没有产品的子类别。要将其更改为返回上面的报告,您必须将最后一个子类别级别的外部联接到产品,并使用
IFNULL(prd\u name,'notapplication')作为prd\u name
。 不完全是你要求的,但遵循一些事实上的标准。。。 查询中包含输入数据;您所要做的就是删除WITH子句

    WITH
    category(cat_id,cat_name,parent_cat) AS (
                        SELECT 1,'TV',NULL::INT
    UNION ALL SELECT 2,'LCD',1
    UNION ALL SELECT 3,'PLASMA',1
    )
    ,
    product(prd_id,prd_name,prd_cat) AS (
                        SELECT 1,'LG',1
    UNION ALL SELECT 2,'HD',2
    UNION ALL SELECT 3,'FHD',2
    )
    SELECT
        prd.prd_id       AS prd_id
    , cat_l1.cat_name  AS cat_l1_name
    , cat_l1.cat_name  AS cat_l2_name
    , prd.prd_name     AS prd_name
    FROM category cat_l1
    JOIN product  prd
        ON prd_cat = cat_l1.cat_id
    WHERE cat_l1.parent_cat IS NULL
    UNION ALL
    SELECT
        prd.prd_id       AS prd_id
    , cat_l2.cat_name  AS cat_l2_name
    , cat_l1.cat_name  AS cat_l1_name
    , prd.prd_name     AS prd_name
    FROM category cat_l1
    JOIN category cat_l2
        ON cat_l2.parent_cat = cat_l1.cat_id
    JOIN product  prd
        ON prd_cat = cat_l2.cat_id
    WHERE cat_l1.parent_cat IS NULL
    ;

prd_id|cat_l1_name|cat_l2_name|prd_name
     1|TV         |TV         |LG
     2|LCD        |TV         |HD
     3|LCD        |TV         |FHD
玩得开心


理智的马可

会计师,你这里的不是一个不平衡的层次结构(层次结构树的各个分支的长度不同),而是一个参差不齐的层次结构

当你有一个固定的最低级别(产品,在你的情况下)和一个不平衡的层次结构(类别,在你的情况下)时,层次结构是参差不齐的

因此,理论上:

cat_l1|cat_l2|prd
TV    |NULL  |LG
TV    |LCD   |HD
TV    |LCD   |FHD
TV    |PLASMA|NULL
我的答案基于设计和填充包含这种层次结构的维度表的事实标准。 最低级别是主键级别,因此它是产品。经典的表格设计将主键放在第一位。然后,我继续按列中预期基数的顺序-向下分层

填充参差不齐层次结构中的漏洞是通过人工平衡除最低层之外的所有层来实现的:您向下复制父层,直到所有层都被填充

您没有用于PLASMA子类别的产品。使用此设计,您要么不为该子类别创建任何行,要么创建一个“不适用”的产品条目,例如,带有负ID。如下所示:

cat_l1|cat_l2|prd
TV    |TV    |LG
TV    |LCD   |HD
TV    |LCD   |FHD
TV    |PLASMA|not applicable
下面的脚本抑制了没有产品的子类别。要将其更改为返回上面的报告,您必须将最后一个子类别级别的外部联接到产品,并使用
IFNULL(prd\u name,'notapplication')作为prd\u name
。 不完全是你要求的,但遵循一些事实上的标准。。。 查询中包含输入数据;您所要做的就是删除WITH子句

    WITH
    category(cat_id,cat_name,parent_cat) AS (
                        SELECT 1,'TV',NULL::INT
    UNION ALL SELECT 2,'LCD',1
    UNION ALL SELECT 3,'PLASMA',1
    )
    ,
    product(prd_id,prd_name,prd_cat) AS (
                        SELECT 1,'LG',1
    UNION ALL SELECT 2,'HD',2
    UNION ALL SELECT 3,'FHD',2
    )
    SELECT
        prd.prd_id       AS prd_id
    , cat_l1.cat_name  AS cat_l1_name
    , cat_l1.cat_name  AS cat_l2_name
    , prd.prd_name     AS prd_name
    FROM category cat_l1
    JOIN product  prd
        ON prd_cat = cat_l1.cat_id
    WHERE cat_l1.parent_cat IS NULL
    UNION ALL
    SELECT
        prd.prd_id       AS prd_id
    , cat_l2.cat_name  AS cat_l2_name
    , cat_l1.cat_name  AS cat_l1_name
    , prd.prd_name     AS prd_name
    FROM category cat_l1
    JOIN category cat_l2
        ON cat_l2.parent_cat = cat_l1.cat_id
    JOIN product  prd
        ON prd_cat = cat_l2.cat_id
    WHERE cat_l1.parent_cat IS NULL
    ;

prd_id|cat_l1_name|cat_l2_name|prd_name
     1|TV         |TV         |LG
     2|LCD        |TV         |HD
     3|LCD        |TV         |FHD
玩得开心


理智的马可

您可以通过首先消除拥有两个表的复杂性来解决这个问题。创建一个将类别记录与产品记录相结合的视图,如下所示:

create view combi as
  select 'P' as type, 
         id, 
         prd_name as name, 
         prd_cat as parent_id
  from   product
  union all
  select 'C' as type, 
         id,
         cat_name, 
         parent_cat
  from   category;
现在,您可以基于此视图进行查询,确保在联接条件中添加类型要求:

select    lvl1.name as lvl1,
          lvl2.name as lvl2,
          lvl3.name as lvl3
from      combi as lvl1
left join combi as lvl2 on lvl1.id = lvl2.parent_id and lvl1.type = 'C'
left join combi as lvl3 on lvl2.id = lvl3.parent_id and lvl2.type = 'C'
where     lvl1.parent_id is null;
请参见在以下位置运行它:


您可以通过首先消除拥有两个表的复杂性来解决这个问题。创建一个将类别记录与产品记录相结合的视图,如下所示:

create view combi as
  select 'P' as type, 
         id, 
         prd_name as name, 
         prd_cat as parent_id
  from   product
  union all
  select 'C' as type, 
         id,
         cat_name, 
         parent_cat
  from   category;
现在,您可以基于此视图进行查询,确保在联接条件中添加类型要求:

select    lvl1.name as lvl1,
          lvl2.name as lvl2,
          lvl3.name as lvl3
from      combi as lvl1
left join combi as lvl2 on lvl1.id = lvl2.parent_id and lvl1.type = 'C'
left join combi as lvl3 on lvl2.id = lvl3.parent_id and lvl2.type = 'C'
where     lvl1.parent_id is null;
请参见在以下位置运行它:


您的
分类表有多深?它可能有3级,4级,…?可能重复@PhamX.Bach,是的,这个产品树是4级。我将在账户树中应用相同的树概念,这将更加深入,可能是7个层次。@accounterم这个问题已经被问过很多次了。搜索树遍历或分层数据将为您提供答案。@mroach感谢您的链接。我的问题是我有另一个表(产品),它也应该被视为树中的一个节点。您的
类别
表有多深?它可能有3级,4级,…?可能重复@PhamX.Bach,是的,这个产品树是4级。我将在账户树中应用相同的树概念,这将更加深入,可能是7个层次。@accounterم这个问题已经被问过很多次了。搜索树遍历或分层数据将为您提供答案。@mroach感谢您的链接。我的问题是我哈