电子商务,类别和类别浏览产品

Rag*_*geZ 1 php database-design e-commerce

我正在为客户建立一个EC网站,项目经理带来了一些奇怪的想法,我正在努力实际实现他卖给客户的东西.

这是我的主要问题和快速总结系统的设置方式:产品属于类别,类别可能是另一类别的子类.因此,该类别在网站的左侧边栏中显示为树.

用户可以浏览任何类别,甚至是非"叶子"类别,如果用户点击非叶类别,那么应该在1级类别上呈现类似的列表(同样适用于2级类别):

big category 1
 category level ( 3 or 2 )
  product 1
  product 2
  product 3
 category level ( 3 or 2 ) 
Run Code Online (Sandbox Code Playgroud)

这些东西也应该有一些分页,并在每页上显示5个产品.另外,类别应该以相同的方式排序,它们出现在左侧的菜单中...我的DB方案是这样的:

+-------------+    +-------------+
+ category    +    + product     +
+-------------+    +-------------+
+ category_id +    + product_id  +
+ parent_id   +    + category_id + 
+-------------+    +-------------+
Run Code Online (Sandbox Code Playgroud)

我无法弄清楚我应该如何编写SQL来确保产品按照它们的顺序出现(比如订购产品和类别有菜单).

另外我担心整个设置的性能,如果用户选择非"叶子"类别,我将不得不搜索所有子类别并创建一个大类别IN(id1,id2,id3),我知道经验长IN语句表现不佳.

如果有人遇到相同的设计/问题,并有一些建议如何制作它,我将不胜感激.

Bil*_*win 6

您可以使用物化路径设计.目录路径是物化路径的示例.也就是说,一系列的祖先值连接在一起,其中一些字符("/"或","是常见的)将它们分开.

所以你可能有类别:

+---------------------------------------------+
| cat_id | Name            | cat_path | depth |
+---------------------------------------------+
|    1   | Electronics     | 1/       |   1   |
|    2   | Digital cameras | 1/2/     |   2   |
|    3   | SLR cameras     | 1/2/3/   |   3   |
|    4   | Audio           | 1/4/     |   2   |
|    5   | Speakers        | 1/4/5/   |   3   |
|    6   | Wall Satellites | 1/4/5/6/ |   4   |
|    7   | Computers       | 1/7/     |   2   |
+---------------------------------------------+
Run Code Online (Sandbox Code Playgroud)

现在,如果您想要所有在Audio下的产品,您可以执行以下查询:

SELECT p.*, pc.*
FROM Products p JOIN Categories pc ON (p.cat_id = pc.cat_id)
JOIN Categories c ON (pc.cat_path LIKE c.cat_path||'%')
WHERE c.name = 'Audio';
Run Code Online (Sandbox Code Playgroud)

例如,'1/4/5/6' LIKE '1/4/%'确实如此,因此包括了Wall Satellites.对于Audio的任何其他子类别也是如此.


关于菜单渲染的问题:我假设你想要菜单渲染: - 所选类别的所有祖先 - 所选类别的祖先的所有兄弟姐妹

因此,如果您选择"扬声器",您会看到:

  • 电子产品
    • 音频
      • 音箱
    • 电脑
    • 数码相机

但是你不想要计算机或数码相机的后代(即扬声器的"表兄弟").

SELECT uncle.name, uncle.depth
FROM Categories chosen
JOIN Categories ancestor ON (chosen.cat_path LIKE ancestor.cat_path||'%')
JOIN Categories uncle ON (ancestor.depth = uncle.depth
  AND SUBSTRING(REVERSE(ancestor.cat_path), 3, 100) = SUBSTRING(REVERSE(uncle.cat_path), 3, 100))
WHERE chosen.name = 'Speakers'
ORDER BY uncle.depth, uncle.name;
Run Code Online (Sandbox Code Playgroud)

我正在使用一种技巧来检测叔叔:在剥离最后一个元素之后比较路径.为此,请反转字符串,然后剥离第一个元素.这应该至少在MySQL和MS SQL Server中有效,但REVERSE()不是标准的,可能无法移植到其他品牌的RDBMS.

请注意,您应该允许每个元素使用多个数字cat_path,在这种情况下,子字符串偏移量也应该增加.