mysql如何进行数据透视,mysql-如何优化数据透视表的条件检查?

在recent question中,StevieG向我展示了如何解决数据透视表的问题.新的问题是我必须检查数据透视表上的某些条件.让我们进行最后的查询:

SELECT

c.id,

GROUP_CONCAT(if(d.name = 'p1', d.value, NULL)) AS 'p1',

GROUP_CONCAT(if(d.name = 'p2', d.value, NULL)) AS 'p2',

GROUP_CONCAT(if(d.name = 'p3', d.value, NULL)) AS 'p3',

GROUP_CONCAT(if(d.name = 'p4', d.value, NULL)) AS 'p4',

GROUP_CONCAT(if(d.name = 'p5', d.value, NULL)) AS 'p5',

GROUP_CONCAT(if(d.name = 'p6', d.value, NULL)) AS 'p6'

FROM container c

JOIN data d ON c.id = d.container

GROUP BY c.id

显然,我无法添加WHERE子句(例如,如果我想检查p5> 30).我发现了两种方法可以解决此问题.首先是通过在派生表中进行转换:

SELECT * FROM (

SELECT

c.id,

GROUP_CONCAT(if(d.name = 'p1', d.value, NULL)) AS 'p1',

GROUP_CONCAT(if(d.name = 'p2', d.value, NULL)) AS 'p2',

GROUP_CONCAT(if(d.name = 'p3', d.value, NULL)) AS 'p3',

GROUP_CONCAT(if(d.name = 'p4', d.value, NULL)) AS 'p4',

GROUP_CONCAT(if(d.name = 'p5', d.value, NULL)) AS 'p5',

GROUP_CONCAT(if(d.name = 'p6', d.value, NULL)) AS 'p6'

FROM container c

JOIN data d ON c.id = d.container

GROUP BY c.id

) WHERE p5>30

我发现的另一种方法是添加HAVING子句:

SELECT

c.id,

GROUP_CONCAT(if(d.name = 'p1', d.value, NULL)) AS 'p1',

GROUP_CONCAT(if(d.name = 'p2', d.value, NULL)) AS 'p2',

GROUP_CONCAT(if(d.name = 'p3', d.value, NULL)) AS 'p3',

GROUP_CONCAT(if(d.name = 'p4', d.value, NULL)) AS 'p4',

GROUP_CONCAT(if(d.name = 'p5', d.value, NULL)) AS 'p5',

GROUP_CONCAT(if(d.name = 'p6', d.value, NULL)) AS 'p6'

FROM container c

JOIN data d ON c.id = d.container

GROUP BY c.id

HAVING p5>30

问题在于性能.我使用的测试数据库有50.000个条目,但产量可能高达100万.第一个句子(没有检查p5> 30的那个句子)在我的开发计算机(没有缓存)中执行1000个句子需要0’60秒,但是第二个和第三个句子要花5分钟以上的时间才能完成.

我知道有一个不带数据索引的隐式派生表生成,但是我有什么选择来优化它呢?

解决方法:

由于数据(容器,名称)是唯一的,因此您无需使用GROUP_CONCAT.

那这个呢:

SELECT

c.id,

d_p1.value AS 'p1',

d_p2.value AS 'p2',

d_p3.value AS 'p3',

d_p4.value AS 'p4',

d_p5.value AS 'p5'

FROM container AS c

LEFT JOIN data AS d_p1 ON (d_p1.container = c.id AND d_p1.name = 'p1')

LEFT JOIN data AS d_p2 ON (d_p2.container = c.id AND d_p2.name = 'p2')

LEFT JOIN data AS d_p3 ON (d_p3.container = c.id AND d_p3.name = 'p3')

LEFT JOIN data AS d_p4 ON (d_p4.container = c.id AND d_p4.name = 'p4')

LEFT JOIN data AS d_p5 ON (d_p5.container = c.id AND d_p5.name = 'p5')

WHERE d_p5.value > 30

如果数据(容器,名称)上有索引,则查询应在几秒钟内运行.

如果data.name的长度超过几个字符(例如5个字符),则应该使用替代键(整数)代替data.name.

标签:query-optimization,mysql

来源: https://codeday.me/bug/20191127/2074549.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值