结合SQL SUM子句

时间:2013-07-21 16:36:02

标签: mysql sql performance geographic-distance

我有一个脚本需要在同一个数据子集上执行四个相当大的MySQL查询。有没有办法将它们组合成一个查询?

以下是查询的内容:

Select sum(value) From 
    ( Select lat, lng, value From `pop_geo_199` Where (
         (lat Between 38.1768916977 And 39.6131083023) And (lng Between -77.9596650363 And -76.1143349637)) 
        ) As FirstCut 
Where (acos(0.627895140732*sin(radians(lat)) + 0.778297945677*cos(radians(lat))*cos(radians(lng)-(-1.34454929586))) * 6371 < 79.85)

正如您可能知道的那样,这是纬度和经度点的地理查询。查询的作用是首先创建总表(FirstCut)的简单方形子集,然后在其上运行trig函数以获得圆形区域。

据我所知,查询中缓慢的部分是FirstCut,因为它所绘制的表有大约280万行。但是,FirstCut,在这种情况下,只有大约27,922行,所以通过比较,trig部分超快。

问题是,我必须运行其中一些。但是,它们都可以使用相同的FirstCut,因为它们是以同一区域为中心的不同半径。我希望只用一个查询而不是四个查询来解决这个问题。

以下是第二个查询的内容:

Select sum(value) From 
    ( Select lat, lng, value From `pop_geo_199` Where (
         (lat Between 38.1768916977 And 39.6131083023) And (lng Between -77.9596650363 And -76.1143349637)) 
        ) As FirstCut 
Where (acos(0.627895140732*sin(radians(lat)) + 0.778297945677*cos(radians(lat))*cos(radians(lng)-(-1.34454929586))) * 6371 < 48.57) 

正如你所看到的,它与另一个完全相同,只是最后一个WHERE子句略有不同 - 条件只是一个较小的半径(48.57而不是79.85)。

如何以有效的方式将这两个查询合并为一个查询?

我尝试过使用CASE条款 - 这是最好的方法吗?

Select 

sum(case when (acos(0.627895140732*sin(radians(lat)) + 0.778297945677*cos(radians(lat))*cos(radians(lng)-(-1.34454929586))) * 6371 < 79.85) then value else 0 end),

sum(case when (acos(0.627895140732*sin(radians(lat)) + 0.778297945677*cos(radians(lat))*cos(radians(lng)-(-1.34454929586))) * 6371 < 48.57) then value else 0 end)

From ( Select lat, lng, value From `pop_geo_199` Where ((lat Between 38.1768916977 And 39.6131083023) And (lng Between -77.9596650363 And -76.1143349637)) ) As FirstCut;

1 个答案:

答案 0 :(得分:1)

您可以使用CASE语句。您还可以将计算移动到子查询中:

Select 
     sum(case 
           when rad < 79.85
           then value 
           else 0 end)  1stQuerySum,
     sum(case 
           when rad < 48.57 
           then value 
           else 0 end)  2ndQuerySum
From  ( 
    Select lat, lng, value, 
           acos(0.627895140732*sin(radians(lat)) + 0.778297945677*cos(radians(lat))*cos(radians(lng)-(-1.34454929586))) * 6371 rad
    From `pop_geo_199` 
    Where (
         (lat Between 38.1768916977 And 39.6131083023) And 
         (lng Between -77.9596650363 And -76.1143349637)
    ) 
) As FirstCut