Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/325.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 在表B中查找表A中最大值的详细信息的嵌套查询_Sql_Mysql_Nested_Subquery_Max - Fatal编程技术网

Sql 在表B中查找表A中最大值的详细信息的嵌套查询

Sql 在表B中查找表A中最大值的详细信息的嵌套查询,sql,mysql,nested,subquery,max,Sql,Mysql,Nested,Subquery,Max,我有很多航班往返于机场之间 每个机场都有一个ID和x,y坐标 对于属于某个用户的给定航班列表,我希望找到访问过的最北端最高的y机场 以下是我当前使用的查询: SELECT name,iata,icao,apid,x,y FROM airports WHERE y=(SELECT MAX(y) FROM airports AS a , flights AS f WHERE (f.src_apid=a.apid

我有很多航班往返于机场之间

每个机场都有一个ID和x,y坐标

对于属于某个用户的给定航班列表,我希望找到访问过的最北端最高的y机场

以下是我当前使用的查询:

SELECT name,iata,icao,apid,x,y 
  FROM airports 
 WHERE y=(SELECT MAX(y) 
            FROM airports AS a
               , flights AS f 
           WHERE (f.src_apid=a.apid OR f.dst_apid=a.apid) AND f.uid=[user_id]
         )
只要y是唯一的,这项工作就会非常漂亮,速度也相当快=在那个纬度只有一个机场,但如果不是,它就会失败。不幸的是,这种情况经常发生,例如,军用机场和民用机场有单独的入口,尽管它们占据相同的坐标

我真正想做的是在子查询中找到带有MAXy的airport并返回实际匹配的airport a.apid,而不是返回y的值然后再次匹配它。有什么建议吗

假设用户只有一次从apid“3728”起飞的航班:

mysql> select * from flights where uid=35 and src_apid=3728 limit 1;
+------+----------+----------+----------+----------+------+------+-----------+-------+--------+------+------+------+--------+----------+--------------+--------------+---------------------+------+------------+------+
| uid  | src_apid | src_time | dst_apid | distance | code | seat | seat_type | class | reason | plid | alid | trid | fid    | duration | registration | note         | upd_time            | opp  | src_date   | mode |
+------+----------+----------+----------+----------+------+------+-----------+-------+--------+------+------+------+--------+----------+--------------+--------------+---------------------+------+------------+------+
|   35 |     3728 | NULL     |     3992 |     4116 | NW16 | 23C  | A         | Y     | L      |  167 | 3731 | NULL | 107493 | 08:00:00 |              | del. typhoon | 2008-10-04 10:40:58 | Y    | 2001-08-22 | F    | 
+------+----------+----------+----------+----------+------+------+-----------+-------+--------+------+------+------+--------+----------+--------------+--------------+---------------------+------+------------+------+
在同一坐标上有两个机场:

mysql> select * from airports where y=21.318681;
+-----------------------+----------+---------------+------+------+-------------+-----------+-----------+------+------+----------+------+
| name                  | city     | country       | iata | icao | x           | y         | elevation | apid | uid  | timezone | dst  |
+-----------------------+----------+---------------+------+------+-------------+-----------+-----------+------+------+----------+------+
| Honolulu Intl         | Honolulu | United States | HNL  | PHNL | -157.922428 | 21.318681 |        13 | 3728 | NULL |      -10 | N    | 
| Hickam Air Force Base | Honolulu | United States |      | PHIK | -157.922428 | 21.318681 |        13 | 7055 |    3 |      -10 | N    | 
+-----------------------+----------+---------------+------+------+-------------+-----------+-----------+------+------+----------+------+

如果运行原始查询,子查询将返回y=21.318681,这反过来将匹配apid 3728正确或apid 7055错误。

第三次尝试,使用假定的用户userid,name table

select u.name, ap.name
     , ap.iata
     , ap.icao
     , ap.apid
     , ap.x
     , max(ap.y)  
  from users u
     , airports ap
     , flights f
 where u.userid=f.userid
   and (   f.src_apid=ap.apid 
        OR f.dst_apid=ap.apid
       )
group by u.name, ap.name,ap.iata,ap.icao,ap.apid,ap.x 
您现在可以将查询限制为您感兴趣的一个用户

对分组的评论:

严格地说,MySQL允许我将这个组写成“groupbyU.name,ap.name”。 其他SQL方言则没有,它们要求所有未聚合的选定字段都在GROUPBY语句中。 所以我在按字段选择组时倾向于“胆小鬼”。。。 那么这个呢:

SELECT name,iata,icao,apid,x,y 
FROM airports AS a, flights AS f 
WHERE f.src_apid=a.apid OR f.dst_apid=a.apid
ORDER BY y DESC LIMIT 1

您选择相关用户的所有航班,从北方到南方订购,并从列表中选择第一个航班。

以下查询如何执行? 它的工作原理是首先在所访问的机场中找到最北端的科迪奈特。然后执行相同的查询,该查询在上一次查询中按Y坐标进行过滤。最后一步是找到机场

drop table airports;
drop table flights;

create table airports(
   apid    int         not null
  ,apname  varchar(50) not null
  ,x       int         not null
  ,y       int         not null
  ,primary key(apid)
  ,unique(apname)
);

create table flights(
   flight_id int         not null auto_increment
  ,src_apid  int         not null
  ,dst_apid  int         not null
  ,user_id   varchar(20) not null
  ,foreign key(src_apid) references airports(apid)
  ,foreign key(dst_apid) references airports(apid)
  ,primary key(flight_id)
  ,index(user_id)
);

insert into airports(apid, apname, x, y) values(1, 'Northpole Civilian',     50, 100);
insert into airports(apid, apname, x, y) values(2, 'Northpole Military',     50, 100);
insert into airports(apid, apname, x, y) values(3, 'Transit point',          50, 50);
insert into airports(apid, apname, x, y) values(4, 'Southpole Civilian',     50, 0);
insert into airports(apid, apname, x, y) values(5, 'Southpole Military',     50, 0);

insert into flights(src_apid, dst_apid, user_id) values(4, 3, 'Family guy');
insert into flights(src_apid, dst_apid, user_id) values(3, 1, 'Family guy');

insert into flights(src_apid, dst_apid, user_id) values(5, 3, 'Mr Bazooka');
insert into flights(src_apid, dst_apid, user_id) values(3, 2, 'Mr Bazooka');

select airports.apid
      ,airports.apname
      ,airports.x
      ,airports.y
  from (select max(a.y) as y
          from flights  f
          join airports a on (a.apid = f.src_apid or a.apid = f.dst_apid)
         where f.user_id = 'Family guy'
       ) as northmost 
  join (select a.apid
              ,a.y
          from flights  f
          join airports a on (a.apid = f.src_apid or a.apid = f.dst_apid)
         where f.user_id = 'Family guy'
       ) as userflights on(northmost.y = userflights.y)   
  join airports on(userflights.apid = airports.apid);
编辑。对优化器来说比较容易混淆的替代查询


好吧,也许是这样的:

SELECT name, iata, icao, apid, x, y
  FROM airports
  WHERE y = (SELECT MAX(A.y)
               FROM airports AS a
             INNER JOIN flights AS f
               ON (F.SRC_APID = A.APID OR
                   F.DST_APID = A.APID)
               WHERE f.uid = [user_id]) AND
        apid IN (SELECT SRC_APID AS APID
                   FROM FLIGHTS
                   WHERE UID = [user_id]
                 UNION ALL
                 SELECT DEST_APID AS APID
                   FROM FLIGHTS
                   WHERE UID = [user_id])
无法保证这将如何执行,但也许这是朝着正确方向迈出的一步


分享和享受。

应该更清楚一点:比如火奴鲁鲁,同时是民用机场代码PHNL和军用机场代码PHIK,因此显示为两个不同的机场,恰好具有相同的坐标。您的查询仍将同时返回这两个结果。好的,这将有点困难。。你想去两个机场中的哪一个?是否有要应用的排序标准?或者apid=AirPortID对于PHIK和PHNL是相同的?apid是机场的唯一键,因此PHIK和PHNL有不同的键,我需要查看最初匹配的键,即机场的apid等于f.src_apid或f.dst_apid。一个更具体的例子:用户X从f.uid=X从火奴鲁鲁PHNL到悉尼的航班中选择了一个航班,我想知道用户X最北端的机场。答案应该是火奴鲁鲁PHNL,而不是Hickam AFB PHIK。你们有用户的桌子吗?如果您可以加入,那么您就可以使用group by实现您的目标。是的,有一个用户表,但是上面的查询速度非常慢-根据描述,它从一个临时表开始,并对342118行进行文件排序=这主意不错,但descripe说,查询首先对所有机场进行排序,然后进行过滤,因此速度相当慢:对于一个典型用户,即使y、src_apid、dst_apid都被索引了,也只有2.7秒。apid的选择是任意的——你不能保证每次都得到相同的值。事实上,根据雷克萨斯回答中的评论,没有办法支持选择最北部机场的要求,因为数据不在系统中。嗯?上面的查询在示例数据中创建了用户的机场3728和3992的列表,并按y对这些匹配的机场进行排序,因此我看不出它如何返回错误的7055。您能否在机场和航班中给出几个示例行,以显示问题以及预期结果集?我很乐意提供帮助,但我对这个问题理解得不够清楚。查询应该修改为只返回乘客访问过的机场,即在显示的示例数据中,乘客访问了3728和3992,因此只应返回其中一个机场,从而消除了Hickam apid=7055.Oh,在我写这篇文章时,我没有看到您添加了示例数据。你想让我用你的例子来代替吗?叮叮,我想我们赢了!获得正确的结果,并且启动速度非常快。唯一有点吓人的是临时表格,上面描述说需要文件排序,但我会尝试一些病理病例并报告回来。调查显示:4000次以上的航班,0.23秒的时间是非常值得尊敬的,40000次航班,3.15秒的时间是可以容忍的。赏金是你的!令人惊叹的您最终使用了哪些查询?顺便说一句,出于某种原因,您使用了一个separ
ate单击“需要回答”旁边的“悬赏奖励”图标,以奖励优秀尝试的悬赏+1。唉,这只是Ronnis回答速度的一半,因为你实际上获得了用户的两次航班。
SELECT name, iata, icao, apid, x, y
  FROM airports
  WHERE y = (SELECT MAX(A.y)
               FROM airports AS a
             INNER JOIN flights AS f
               ON (F.SRC_APID = A.APID OR
                   F.DST_APID = A.APID)
               WHERE f.uid = [user_id]) AND
        apid IN (SELECT SRC_APID AS APID
                   FROM FLIGHTS
                   WHERE UID = [user_id]
                 UNION ALL
                 SELECT DEST_APID AS APID
                   FROM FLIGHTS
                   WHERE UID = [user_id])