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语句表现不佳.
如果有人遇到相同的设计/问题,并有一些建议如何制作它,我将不胜感激.
您可以使用物化路径设计.目录路径是物化路径的示例.也就是说,一系列的祖先值连接在一起,其中一些字符("/"或","是常见的)将它们分开.
所以你可能有类别:
+---------------------------------------------+
| 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,在这种情况下,子字符串偏移量也应该增加.