使用JOIN NULL值匹配DB中的列名

时间:2014-03-04 05:53:34

标签: php mysql sql

我正在尝试创建一个“eBay”样式类别菜单,当用户从多选字段中选择一个项目时,它将添加一个带有任何子类别的新多选项,如果子类别包含子类别,则添加一个新的多选项子子类别。

我有这个主要工作,但我遇到了数据库方面的问题。我有一个名为categories的主表,其中包含两列CatIDCategorycategories表中有三行“Motorcycles”,“Powersports”和“Parts& Accessories”

当用户选择摩托车时,它应该创建一个新的多选并启动摩托车品牌。另一方面,如果用户选择Powersports,它应该创建一个新的多下拉列表并列出Powersport车辆类型“Dirtbike”,“PWC”,“Snowmobile”等。选择其中一个后将显示Powersports->车辆类型 - >品牌多选。

问题是我不知道如何在数据库中正确引用所有这些信息。

例如: 主要类别(类别)

+-------+---------------------+
| CatID | Category            |
+-------+---------------------+
|     1 | Motorcycles         |
|     3 | Parts & Accessories |
|     2 | Powersports         |
+-------+---------------------+

摩托车次分类:(motorcycle_brands)

+-------+-------+-------------------------+
| CatID | SubID | SubName                 |
+-------+-------+-------------------------+
|     1 |     1 | American Classic Motors |
|     1 |     2 | American Ironhorse      |
|     1 |     3 | Aprilia                 |
|     1 |     4 | Benelli                 |
|     1 |     5 | Big Dog                 |
+-------+-------+-------------------------+

Power Sports子类别:(powersport_categories)

+-------+-------+--------------------------------+----+
| CatID | SubID | SubName                        | ID |
+-------+-------+--------------------------------+----+
|     2 |     1 | ATVs                           |  1 |
|     2 |     2 | Dune Buggies / Sand Rails      |  2 |
|     2 |     3 | Go Karts: High-Performance     |  3 |
|     2 |     4 | Personal Watercraft            |  4 |
|     2 |     5 | Powersport Vehicles Under 50cc |  5 |
+-------+-------+--------------------------------+----+

因此,如果我运行以下命令:

SELECT * FROM categories C 
LEFT JOIN motorcycle_brands MB ON MB.CatID = C.CatID 
LEFT JOIN powersport_categories PC ON PC.CatID = C.CatID 
WHERE C.CatID = 1 LIMIT 5;

我明白了:

+-------+-------------+-------------------+-------+-------+-------------------------+-------+-------+---------+------+
| CatID | Category    | CatDBTable        | CatID | SubID | SubName                 | CatID | SubID | SubName | ID   |
+-------+-------------+-------------------+-------+-------+-------------------------+-------+-------+---------+------+
|     1 | Motorcycles | motorcycle_brands |     1 |     1 | American Classic Motors |  NULL |  NULL | NULL    | NULL |
|     1 | Motorcycles | motorcycle_brands |     1 |     2 | American Ironhorse      |  NULL |  NULL | NULL    | NULL |
|     1 | Motorcycles | motorcycle_brands |     1 |     3 | Aprilia                 |  NULL |  NULL | NULL    | NULL |
|     1 | Motorcycles | motorcycle_brands |     1 |     4 | Benelli                 |  NULL |  NULL | NULL    | NULL |
|     1 | Motorcycles | motorcycle_brands |     1 |     5 | Big Dog                 |  NULL |  NULL | NULL    | NULL |
+-------+-------------+-------------------+-------+-------+-------------------------+-------+-------+---------+------+

注意最后的所有NULL值。有没有办法摆脱这些空值?它导致我的代码中出现其他问题,因为当它将此数组返回给我的PHP脚本时,SubIDSubName数组字段为空,因为它与最后一组为NULL。但是,如果我运行与上面相同的查询,将1替换为2,那么我得到了我想要的值,因为它们没有被重复的列名称覆盖。

也许我说这一切都错了我计划在我的所有表中为子类别设置相同的SubIDSubName列,但看起来它可能会让我感到悲伤。我这样做的原因是因为否则我必须编写一个单独的查询,具体取决于选择的值我想要基本上有一个查询,它将基本上为每个子选项完成所有操作。这里有什么改进吗?

2 个答案:

答案 0 :(得分:1)

1)尝试这样的事情(你还应该检查下面我的另一点):

SELECT C.CatID, C.Category, C.CatDBTable, MB.SubID AS MbSubID, MB.SubName AS MbSubName, PC.SubID AS PcSubID, PC.SubName AS PcSubName, PC.ID AS PcID FROM categories C 
LEFT JOIN motorcycle_brands MB ON MB.CatID = C.CatID 
LEFT JOIN powersport_categories PC ON PC.CatID = C.CatID 
WHERE C.CatID = 1 LIMIT 5;

2)如果您使用以下方法,您的数据库结构可能会更好,更具可扩展性(如果您需要添加第4度子程序):

只有一个表名类别,其中包含以下列:

  • ID
  • parent_id(可以为空)
  • 深度
  • 名称

您将按如下方式使用它:

  • "摩托车"这是一个主要类别:(ID => 1,parent_id => null,深度=> 0,名称=>摩托车)
  • " American Classic Motors"这是摩托车"摩托车"将有:(ID => 4,parent_id => 1,深度=> 1,名称=>美国经典汽车)
  • "全地形车"这是美国经典汽车公司的一个子公司"将有:(ID => 5,parent_id => 4,深度=> 2,名称=> ATVs)

答案 1 :(得分:1)

试试这个:

SELECT C.CatID,C.Category,MB.CatID as MBCatID,MB.SubID as MBSubID,MB.SubName as MBSubName,IFNULL(PC.CatID,'') as PCCatID,IFNULL(PC.SubID,'') as PcSubID,IFNULL(PC.SubName,'') as PcSubName,IFNULL(PC.ID,'') as PCID FROM categories C 
    LEFT JOIN motorcycle_brands MB ON MB.CatID = C.CatID 
    LEFT JOIN powersport_categories PC ON PC.CatID = C.CatID 
    WHERE C.CatID = 1 LIMIT 5;

查看SQL Fiddle

中的结果