1

我有两个表,一个用于存储产品,另一个用于存储订单列表。

CREATE TABLE ProductsList(ProductId INT NOT NULL PRIMARY KEY,
                          产品名称 VARCHAR(50))


插入产品列表(产品 ID,产品名称)
                  值(1,'产品 A'),
                        (2,'产品 B'),
                        (3,'产品 C'),
                        (4,'产品 D'),
                        (5,'产品 E'),
                        (6,'产品 F'),
                        (7,'产品 G'),
                        (8,'产品 H'),
                        (9,'产品一'),
                        (10,'产品 J');                        

CREATE TABLE OrderList(OrderId INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
                       EmailId VARCHAR(50),
                       CSVProductIds VARCHAR(50))


插入订单列表(EmailId,CSVProductIds)                       
               值('PersonA@domain.com', '2,4,1,5,7'),
                     ('PersonB@domain.com', '5,7,4'),
                     ('PersonC@domain.com', '2'),
                     ('PersonD@domain.com', '8,9'),
                     ('PersonE@domain.com', '4,5,9'),
                     ('PersonF@domain.com', '1,2,3'),
                     ('PersonG@domain.com', '9,10'),
                     ('PersonH​​@domain.com', '1,5');

输出

ItemName             NoOfOrders
Product A                3
Product B                3 
Product C                1
Product D                3
Product E                4
Product F                0
Product G                2 
Product H                1 
Product I                3 
Product J                1

订单列表将 ItemsId 存储为每个下订单的客户的逗号分隔值。像这样,我的 dB 表中有超过 40k 条记录

现在我被分配了创建报告的任务,我应该在其中显示项目和订购项目的人数,如下所示

我在我的 PHP 中使用如下查询来将订单一个接一个地存储在数组中。

SELECT COUNT(PL.EmailId)
  FROM OrderList PL 
 WHERE CSVProductIds LIKE '2' OR
       CSVProductIds LIKE '%,2,%' OR
       CSVProductIds LIKE '%,2' OR
       CSVProductIds LIKE '2,%'; 

1.是否可以通过使用单一查询获得相同的输出

2.当表中没有更多记录时,在mysql查询中使用like会减慢分贝,即40k行

4

3 回答 3

6

是的,使用带前导通配符的 LIKE 会强制它进行表扫描,即读取表中的每一行。表越大,速度就越慢。例如,它可能会慢数百或数千倍!

这是为什么将逗号分隔的列表存储在 VARCHAR 中并期望访问单个元素对于关系数据库来说是一个糟糕的设计的几个原因之一。

另请参阅我对在数据库列中存储逗号分隔列表真的那么糟糕吗?

您应该做的是定义您的 OrderList 表来存储对电子邮件和 productid。如果订单包含多个产品,则必须存储多行。但这意味着您始终可以找到您正在寻找的单一产品,计算有多少人购买了该产品等,并且您可以通过定义索引来快速进行这些查询。

反对将列表存储在单个列中的规则称为第一范式

于 2012-12-17T05:00:42.197 回答
0

1.使用正则表达式,但考虑到它只改变你的应用程序代码而不是数据库代码。
2.是的,它通常确实会影响此处简短提到的性能,这里有一个可能会有所帮助的解决方案。

于 2012-12-17T05:02:54.430 回答
-1

您可以在下面的单个中找到它

SELECT COUNT(PL.EmailId)
  FROM OrderList PL 
 WHERE FIND_IN_SET(2, CSVProductIds) 
于 2012-12-28T07:20:30.483 回答