mysql - SQL COUNT(*) 是一个 JOIN 语句,而不是嵌套 SELECT 语句中的 COUNT(*),以获得更好的性能

标签 mysql join count large-data-volumes

基于http://www.plumislandmedia.net/mysql/haversine-mysql-nearest-loc/ 以下 SQL 查询返回与给定 $radius 内最接近 $lat/$lon 对的城市数组。我添加了另一个 join-语句 (c.) 来显示每个城市的表 Country 中的 code3l-列。 总的来说,由于 3Mio 条目的数量,此语句大约需要 1.2sek

SELECT population, AccentCity, Country, code3l, name, City, Region,
       Latitude, Longitude, distance, id          
      FROM (
         SELECT z.population,z.id,
                z.AccentCity,z.Country, z.City, z.Region,
                z.Latitude, z.Longitude,
                c.name, c.code3l,
                p.radius,
                p.distance_unit
                         * DEGREES(ACOS(COS(RADIANS(p.latpoint))
                         * COS(RADIANS(z.latitude))
                         * COS(RADIANS(p.longpoint - z.longitude))
                         + SIN(RADIANS(p.latpoint))
                         * SIN(RADIANS(z.latitude)))) AS distance

          FROM worldpopulation AS z
          JOIN (   
                SELECT  '.$lat.'  AS latpoint,  '.$lon.' AS longpoint,
                        '.$radius.' AS radius,      111.045 AS distance_unit
            ) AS p ON 1=1

          JOIN (   
                SELECT * FROM countries
            ) AS c ON c.code2l = z.Country


          WHERE 
            z.population IS NOT NULL 

            AND z.latitude
             BETWEEN p.latpoint  - (p.radius / p.distance_unit)
                 AND p.latpoint  + (p.radius / p.distance_unit)
            AND z.longitude
             BETWEEN p.longpoint - (p.radius / (p.distance_unit * COS(RADIANS(p.latpoint))))
                 AND p.longpoint + (p.radius / (p.distance_unit * COS(RADIANS(p.latpoint))))
         ) AS d
     WHERE distance <= radius
     ORDER BY distance ASC';

除此之外,我还需要添加一些 count(*) 语句来返回每个城市的乘客数量。所以我尝试像这样添加这些:

SELECT population, AccentCity, Country, code3l, name, City, Region,
       Latitude, Longitude, distance,id,
       (select count(*) from passengers where city_id = d.id) AS passenger,
       (select count(*) from passengers where city_id = d.id AND
                                 start = "'.$icao.'") AS passengerFromHere,
       (select count(*) from passengers where city_id = d.id AND
                             destination = "'.$icao.'") AS passengerToHere
FROM (
         SELECT z.population,z.id,
...

但是名为 passengers 的表增长很快,语句的整体执行时间也随之增加

我有一种方法加入繁重的乘客,在更好的执行时间内获得相同的结果(城市数组及其各自的乘客)

最佳答案

我从 SQL 中取出了乘客计数语句。 构建了一个 php 函数,如果名称为 city_id 的键存在,则循环遍历每个城市并将乘客数量添加到该城市

if(isset($cityArray[$passengers[$key[$i]]->city_id]))

作为 sql 语句的替代:

(select count(*) from passengers where city_id = d.id AND
                             start = "'.$icao.'") AS passengerFromHere,

我想出的 codeigniter 函数是这样的:

public function add_PassengersFromHereToCitys($icao, $cityArray){

            $query = $this->db->select('count(city_id) as passengers, city_id')->from('passengers')->where('start', $icao)->group_by('city_id')->get();
            $passengers = $query->result();

            $key = array_keys($passengers);
            $size = sizeOf($key);
            for ($i=0; $i<$size; $i++){

                if(isset($cityArray[$passengers[$key[$i]]->city_id])){
                    $cityArray[$passengers[$key[$i]]->city_id]->passengerFromHere = $passengers[$key[$i]]->passengers;
                }

            }  

            return $cityArray;
        } 

分别使用第二个 count(*) 完成此操作。

现在有了这个 php 循环,获得所需的结果比在 sql 语句中提取日期要快得多。 但是,如果有人有修改sql语句的想法。让我知道!

关于mysql - SQL COUNT(*) 是一个 JOIN 语句,而不是嵌套 SELECT 语句中的 COUNT(*),以获得更好的性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34728702/

相关文章:

php - 仅知道年份的日期(例如 1570-00-00)

mysql - 当某些表为空时如何进行多重连接

mysql - 连接两个表中的特定属性

python - 是否可以在 PYTHON 的一个命令中对多个字符串使用 .count?

php - 单击按钮更新 SQL 表

mysql - 创建 MySQL 触发器时出现语法错误

mysql - 如何创建正确的查询?

Oracle JOIN 使用 + 子查询 : ora-00904 string: invalid identifier

MySQL 在一个查询中对不同表进行多次计数

java - 我的主 java 类如何知道任何其他 java 类中是否引发了任何异常