假设一个products
可以有0个或多个options
-通过下表实现:
products
- id
- name
options
- id
- name
product_options
- id
- product_id
- option_id
进一步假设以下产品具有以下选项:
如何查询此信息,以便获得如下结果:
我的选项实际上是一棵嵌套树。而且它们具有类别表(也是嵌套树)的外键。最终,我需要能够执行此查询并按类别对结果进行分组。但是,我可能应该先了解如何解决这个简单的问题。
更新1:我事先不知道这些选项可能是什么。而且,产品可能具有的选择数量没有限制。
答案 0 :(得分:3)
如果选项数量未知,则可以使用存储过程动态创建可用于旋转表的查询。像这样:
CREATE PROCEDURE display_options()
BEGIN
SET @query = 'SELECT p.id, ';
SET @query = CONCAT(@query, (SELECT GROUP_CONCAT(CONCAT('MAX(CASE WHEN o.name = ''', name, ''' THEN o.name END) AS `', name, '`')) FROM options ORDER BY id));
SET @query = CONCAT_WS(' ', @query,
'FROM products p',
'JOIN product_options po ON po.product_id = p.id',
'JOIN options o ON o.id = po.option_id',
'GROUP BY p.id');
PREPARE stmt FROM @query;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END
此过程将产生这样的查询(与问题中的示例数据的@GordonLinoff答案基本相同):
SELECT p.name,
MAX(CASE WHEN o.name = 'Option 1' THEN o.name END) AS `Option 1`,
MAX(CASE WHEN o.name = 'Option 2' THEN o.name END) AS `Option 2`,
MAX(CASE WHEN o.name = 'Option 3' THEN o.name END) AS `Option 3`,
MAX(CASE WHEN o.name = 'Option 4' THEN o.name END) AS `Option 4`,
MAX(CASE WHEN o.name = 'Option 5' THEN o.name END) AS `Option 5`
FROM products p
JOIN product_options po ON po.product_id = p.id
JOIN options o ON o.id = po.option_id
GROUP BY p.name
然后可以准备并执行以产生如下结果:
name Option 1 Option 2 Option 3 Option 4 Option 5
Product 1 Option 1 Option 2 Option 3
Product 2 Option 2 Option 3 Option 4
Product 3 Option 3 Option 4 Option 5
答案 1 :(得分:3)
经过如此多的试验,我发现以下查询将返回所需的准确结果,即使选项和产品可能增加。
SELECT CONCAT(P.productName, ",", GROUP_CONCAT(COALESCE(IF(P.optionId IN (product_options.option_id),P.optionName,NULL),"NULL") order by P.optionId)) AS result
FROM product_options
RIGHT JOIN (SELECT products.id as productId, products.name as productName,options.id as optionId, options.name AS optionName from products,options)
as P On P.productId = product_options.product_id AND P.optionId = product_options.option_id
GROUP BY P.productId
答案 2 :(得分:2)
如果我理解正确,则可以使用条件聚合:
[a-zA-Z0-9]{3,20}@[a-zA-Z0-9]{3,20}\.[a-zA-Z0-9]{3,20}
答案 3 :(得分:1)
您是否真的需要在数据库级别构建显示?
老实说,如果一切可行,我会节省自己的头绪,然后奔跑:
SELECT p.*, o.*
FROM product_options po
JOIN products p
ON p.id = po.product_id
JOIN options o
ON o.id = po.option_id
WHERE ...
ORDER BY ...
然后在遍历结果集时可以在应用程序级别整理所需的结构
答案 4 :(得分:0)
您可以创建一个具有product_count行×option_count行的结果集,而不是使用具有product_count行×option_count列的结果集:
SELECT products.name
, options.name
, CASE WHEN product_options.id IS NOT NULL THEN 'Y' END
FROM products
CROSS JOIN options
LEFT JOIN product_options ON products.id = product_options.product_id AND options.id = product_options.option_id
结果集将包含产品和选项的所有组合,第三列将包含NULL或Y
。