单位产品计我有这样的一个表:分割从一个表
Count Product
100 apple, orange, mango
50 apple, grape, avocado
20 orange, apple, avocado
如何选择获得这样每个产品的计数?
Count Product
170 apple
120 orange
100 mango
70 avocado
50 grape
单位产品计我有这样的一个表:分割从一个表
Count Product
100 apple, orange, mango
50 apple, grape, avocado
20 orange, apple, avocado
如何选择获得这样每个产品的计数?
Count Product
170 apple
120 orange
100 mango
70 avocado
50 grape
假设Product
是字符列,并且“逗号分隔的列表”的值被存储在它的SQL达到规定的结果是麻烦的。
SQL不是用于将逗号分隔列表中的字符串拆分为单独的行。这个表格设计是面对最佳实践关系数据库设计原则的。
我强烈建议比尔卡尔文的优秀着作“SQL反模式:避免数据库编程的陷阱”。第2章“乱穿马路”,是目前在亚马逊的“往里”功能...
https://www.amazon.com/SQL-Antipatterns-Programming-Pragmatic-Programmers/dp/1934356557
然而,要回答你问的问题。可以达到指定的结果。这将为例如情况下工作,但不一定是其他更一般的情况:
SELECT REPLACE(
REPLACE(
REPLACE(
REPLACE(
REPLACE(
REPLACE(c.Product
,'Apples','Apple'
),'apple','Apple'
),'orange','Orange'
),'mango','Mango'
),'grapes','Grapes'
),'avocado','Avocado'
) AS `Product`
, SUM(c.Count) AS `Count`
FROM (SELECT TRIM(SUBSTRING_INDEX(SUBSTRING_INDEX(d.Product,',',n.i),',',-1)) AS `Product`
, d.Count
FROM (SELECT 1 AS i UNION ALL SELECT 2 UNION ALL SELECT 3) n
CROSS
JOIN (-- table of example data
SELECT 100 AS `Count`, 'Apples, orange, mango' AS `Product`
UNION ALL SELECT 50, 'Apples, grapes, avocado'
UNION ALL SELECT 20, 'Orange, apple, avocado'
) d
) c
GROUP
BY REPLACE(
REPLACE(
REPLACE(
REPLACE(
REPLACE(
REPLACE(c.Product
,'Apples','Apple'
),'apple','Apple'
),'orange','Orange'
),'mango','Mango'
),'grapes','Grapes'
),'avocado','Avocado'
)
ORDER BY 2 DESC, 1 ASC
返回:
Product Count
------- --------
Apple 170
Orange 120
Mango 100
Avocado 70
Grapes 50
该方法适用于例如数据,但不会对其他可能的数据。 (例如,如果用逗号分隔的产品列表中包含四个项目,或者只有两个项目。)
如果你有只是个别Product
归还......我们也许可以使用JOIN一个单独的表在问题中显示的表和表之间,并使用FIND_IN_SET类型操作来执行该匹配。这会使查询变得更简单一些。
爱那本书! – michelek
你确实需要修复表格。也许这就是你想在这里实现的。
我个人:
。
CREATE TABLE product
(
id INT(11) UNSIGNED NOT NULL auto_increment,
product VARCHAR(50) NOT NULL DEFAULT '',
PRIMARY KEY (id),
KEY product (product)
)
engine=innodb
DEFAULT charset=utf8;
现在我把所有可能的产品名称(苹果苹果鳄梨葡萄,芒果橙),可以开始重建你的源表:
SELECT p.product,
Sum(src.count)
FROM product p
LEFT JOIN src
ON src.product REGEXP p.product
GROUP BY p.product
;
--
product Sum(src.count)
apple 170
apples 150
avocado 70
grapes 50
mango 100
orange 120
...嗯什么与苹果的?
一个可能的解决方案是,以取代所有的“苹果”与“苹果”
SELECT Concat('UPDATE src SET product = Replace(product, \'', p2.product, '\', \'', p1.product, '\');') AS q
FROM product p1
LEFT JOIN product p2
ON p1.product != p2.product
AND p2.product REGEXP p1.product
WHERE p2.product IS NOT NULL
;
--
q
UPDATE src SET product = Replace(product, 'apples', 'apple');
MySQL的更换是大小写敏感的,所以我们通过
UPDATE src
SET product = Lower(product);
开始,现在我们可以运行结果前面的查询:
UPDATE src SET product = Replace(product, 'apples', 'apple');
--
2 rows affected
我们修改后的源表:
SELECT * FROM src
;
-
Count Product
100 apple, orange, mango
50 apple, grapes, avocado
20 orange, apple, avocado
让我们重新开始与
而接下来的查询就会让我快乐:
CREATE TABLE inventory AS
SELECT p.product,
Sum(src.count) AS count
FROM product p
LEFT JOIN src
ON src.product REGEXP p.product
GROUP BY p.product
;
SELECT * FROM inventory
;
--
product count
apple 170
avocado 70
grapes 50
mango 100
orange 120
瞧
你有一个产品定义表的地方? – shmosel
我推荐Bill Karwin的优秀书的第2章。 (截至本评论,第2章仍然可以在亚马逊的“Look Inside”中看到... https://www.amazon.com/SQL-Antipatterns-Programming-Pragmatic-Programmers/dp/1934356557 – spencer7593
假设产品和它的计数是原子数据,我建议将模式更改为“(count,product)”元组,而不是使用它们的(合并?)计数来存储产品列表。 –