MySQL使用相同的表优化LEFT加入大数据查询

时间:2013-11-13 13:32:32

标签: mysql

我这里有一个SQL表

| id | dataid |  datarow | datacolumn | datavalue
_________________________________________________
|  1  |  1     |     1    | FirstName   |  John
|  1  |  1     |     1    | LastName    |  Lobo
|  1  |  1     |     1    | Age         |  35
|  1  |  1     |     2    | FirstName   |  Mich
|  1  |  1     |     2    | LastName    |  Handness
|  1  |  1     |     2    | Age         |  22
|  1  |  1     |     3    | FirstName   |  Mike
|  1  |  1     |     3    | LastName    |  Longbow
|  1  |  1     |     3    | Age         |  55

将输出类似这样的内容

FirstName  LastName Age
   John      Lobo   35
   Mich      Handness 22
   Mike      Longbow  55
SELECT DISTINCT     
        t1.datavalue AS Firstname, 
        t2.datavalue AS Lastname,
        t3.datavalue AS Age

FROM largedatatable t1 
        LEFT JOIN (SELECT datavalue,datarow FROM largedatatable WHERE           datacolumn='LastName') t2 ON t1.datarow = t2.datarow
        LEFT JOIN (SELECT datavalue,datarow FROM largedatatable WHERE datacolumn='Age') t3 ON t1.datarow = t3.datarow

WHERE t1.dataid = 1 

这给我的结果如

Firstname  LastName   Age
John        Lobo      35
Mich      Handness    22
Mike      Longbow     55

现在脚本完美无缺;但是如果它的数据集很大,那么查询就会很慢。无论如何我还是可以优化这个SQL查询。谢谢!

2 个答案:

答案 0 :(得分:1)

我认为这可以解决您的问题,或者至少它会运行得更快,因为它只会获取一次表:

select 
    max(case datacolumn when 'FirstName' then datavalue else '' end) as FirstName,
    max(case datacolumn when 'LastName' then datavalue else '' end) as LastName,
    max(case datacolumn when 'Age' then datavalue else '' end) as Age
from 
    large
group by datarow

在小提琴中查看:http://sqlfiddle.com/#!2/f4045/11

答案 1 :(得分:0)

我会确保您在(datarow,datacolumn)上有一个索引来帮助您加入,但您的联接可以简化为

SELECT 
        t1.datavalue AS Firstname, 
        t2.datavalue AS Lastname,
        t3.datavalue AS Age
   FROM 
      largedatatable t1
         LEFT JOIN largedatatable t2
            on t1.datarow = t2.datarow
           and t2.datacolumn = 'LastName'
         LEFT JOIN largedatatable t3
            on t1.datarow = t3.datarow
           and t3.datacolumn = 'Age'
   WHERE
      t1.datacolumn = 'FirstName'

这只会在仅基于第一个名称列的情况下通过主表进行一次,但是从第二个实例中提取列而不需要聚合的MAX()或GROUP BY。