具有动态列的MySQL透视表查询
我使用下表存储产品数据:具有动态列的MySQL透视表查询,mysql,dynamic,pivot,Mysql,Dynamic,Pivot,我使用下表存储产品数据: mysql> SELECT * FROM product; +---------------+---------------+--------+ | id | name | description | stock | +---------------+---------------+--------+ | 1 | product1 | first product | 5 | | 2 | product2 | second produc
mysql> SELECT * FROM product;
+---------------+---------------+--------+
| id | name | description | stock |
+---------------+---------------+--------+
| 1 | product1 | first product | 5 |
| 2 | product2 | second product| 5 |
+---------------+---------------+--------+
mysql> SELECT * FROM product_additional;
+-----------------+------------+
| id | fieldname | fieldvalue |
+-----------------+------------+
| 1 | size | S |
| 1 | height | 103 |
| 2 | size | L |
| 2 | height | 13 |
| 2 | color | black |
+-----------------+------------+
使用以下查询从两个表中选择记录
mysql> SELECT
p.id
, p.name
, p.description
,MAX(IF(pa.fieldname = 'size', pa.fieldvalue, NULL)) as `size`
,MAX(IF(pa.fieldname = 'height', pa.fieldvalue, NULL)) as `height`
,MAX(IF(pa.fieldname = 'color', pa.fieldvalue, NULL)) as `color`
FROM product p
LEFT JOIN product_additional AS pa ON p.id = pa.id
GROUP BY p.id
+---------------+---------------+--------+---------+--------+
| id | name | description | size | height | color |
+---------------+---------------+--------+---------+--------+
| 1 | product1 | first product | S | 103 | null |
| 2 | product2 | second product| L | 13 | black |
+---------------+---------------+--------+---------+--------+
一切正常:)
因为我动态地填充“附加”表,所以如果查询也是动态的,那就更好了。这样,我就不必每次输入新的字段名和字段值时都更改查询。在MySQL中,动态执行此操作的唯一方法是使用准备好的语句。下面是一篇关于他们的好文章: 您的代码如下所示:
SET @sql = NULL;
SELECT
GROUP_CONCAT(DISTINCT
CONCAT(
'MAX(IF(pa.fieldname = ''',
fieldname,
''', pa.fieldvalue, NULL)) AS ',
fieldname
)
) INTO @sql
FROM product_additional;
SET @sql = CONCAT('SELECT p.id
, p.name
, p.description, ', @sql, '
FROM product p
LEFT JOIN product_additional AS pa
ON p.id = pa.id
GROUP BY p.id, p.name, p.description');
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
看
注意:GROUP_CONCAT函数的限制为1024个字符。请参见参数组_concat_max_len这里的存储过程,它将根据一个表和列中的数据以及其他表和列中的数据生成表 使用函数“sum(如果(col=value,1,0))作为值”。您可以从不同的函数中进行选择,如MAX(if())等
我的方法与公认的答案略有不同。通过这种方式,您可以避免使用默认限制为1024个字符的GROUP_CONCAT,并且如果有很多字段,除非更改限制,否则将无法使用
SET @sql = '';
SELECT
@sql := CONCAT(@sql,if(@sql='','',', '),temp.output)
FROM
(
SELECT
DISTINCT
CONCAT(
'MAX(IF(pa.fieldname = ''',
fieldname,
''', pa.fieldvalue, NULL)) AS ',
fieldname
) as output
FROM
product_additional
) as temp;
SET @sql = CONCAT('SELECT p.id
, p.name
, p.description, ', @sql, '
FROM product p
LEFT JOIN product_additional AS pa
ON p.id = pa.id
GROUP BY p.id, p.name, p.description');
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
感谢您的快速回答!在PHP中,这意味着我要做两个查询。一个用于获取列字符串,另一个用于将字符串合并到完整查询中?在这里使用Zend Framework。@fr0sty您必须在PHP中测试它。我不确定你将如何处理这段代码。我只是使用了这个例子,并重新应用它从wp_帖子和wp_Posteta中提取数据,这是一个巨大的帮助。非常感谢。我唯一需要添加的是调用设置group_concat_max_len=150000;所以它不会发出警告。这是一个很大的帮助。我将此方法应用于类似的问题,而不是使用SELECT语句,而是每隔几个小时创建一个事件,以重新生成一个视图,该视图将n行从一个表旋转到另一个表的n列中。这是一个很大的帮助,因为在每次执行SELECT之前,我都在使用PHP重建查询。尽管视图不能利用索引,但我认为过滤性能不会成为问题,因为数据透视行->列表示特许经营公司员工接受的培训类型,因此视图不会中断几千行。谢谢@bluefeet@JuanCarlosOropeza感谢您让我知道,我用dbfiddle替换了链接。在mySQL workbench中运行该链接时,我收到了一个错误。怎么跑?对我来说很有效。这将取决于你的错误最终,一个真正的答案!谢谢,事实上,我在
GROUP\u CONCAT
和很多字段上遇到了麻烦。谢谢!!通过定义组连接限制的方式,设置会话组连接最大长度=1000000;上面是为会话集全局组设置的\u concat\u max\u len=1000000@GrumpyCivet您遇到的问题很可能是由于启用了仅\u FULL\u GROUP\u BY
。简单的解决方案是填充生成查询的GROUPBY子句中的其余列。。。。我现在已经做到了。所以它应该会起作用。这里有一把小提琴在工作
SET @sql = '';
SELECT
@sql := CONCAT(@sql,if(@sql='','',', '),temp.output)
FROM
(
SELECT
DISTINCT
CONCAT(
'MAX(IF(pa.fieldname = ''',
fieldname,
''', pa.fieldvalue, NULL)) AS ',
fieldname
) as output
FROM
product_additional
) as temp;
SET @sql = CONCAT('SELECT p.id
, p.name
, p.description, ', @sql, '
FROM product p
LEFT JOIN product_additional AS pa
ON p.id = pa.id
GROUP BY p.id, p.name, p.description');
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;