简体   繁体   English

MySQL选择内部联接(仅唯一)

[英]MySQL Select Inner Join (Only Unique)

In my app, I have vehicles which are assigned to a specific class. 在我的应用中,我有分配给特定类别的车辆。 In the query below I am trying to select all classes which have at least one vehicle in it that is in a certain area. 在下面的查询中,我试图选择其中某个区域内至少有一辆车辆的所有类别。

The code below works fine, however if there are multiple vehicles inside of the class that fit the location parameter, multiple instances of the class are returned in the results. 下面的代码运行良好,但是,如果类中有多个适合位置参数的车辆,则结果中将返回该类的多个实例。

How can I structure this query so only one instance of every class is returned, regardless of how many vehicles inside of the class fit the paramater? 如何构造该查询,以便无论类中有多少适合该参数的车辆返回每个类的一个实例?

$get_veh = $pdo->prepare("SELECT * FROM tbl_car_class_category JOIN tbl_vehicles ON tbl_vehicles.veh_class_id = tbl_car_class_category.id_class_cat WHERE tbl_vehicles.veh_advanceLng between (:loc_long-:radius/cos(radians(:loc_lat))*69) and (:loc_long+:radius/cos(radians(:loc_lat))*69) and veh_advanceLat between (:loc_lat-(:radius/69)) and (:loc_lat+(:radius/69)) AND veh_status=:veh_status");

$get_veh->bindparam(":veh_status", $veh_status);
$get_veh->bindparam(":loc_lat", $loc_lat);
$get_veh->bindparam(":loc_long", $loc_long);
$get_veh->bindparam(":radius", $radius);

$get_veh->execute();

If the intent is return just rows from the category table, we could replace the JOIN with an EXISTS (correlated subquery) 如果意图是仅返回类别表中的行,则可以用EXISTS (correlated subquery)替换JOIN

For example: 例如:

 SELECT c.*
   FROM tbl_car_class_category c
  WHERE EXISTS
      ( SELECT 1 
          FROM tbl_vehicles v 
         WHERE v.veh_class_id = c.id_class_cat
           AND v.veh_advanceLng 
               BETWEEN (:loc_long-:radius/cos(radians(:loc_lat))*69)
                   AND (:loc_long+:radius/cos(radians(:loc_lat))*69)
           AND v.veh_advanceLat
               BETWEEN (:loc_lat-(:radius/69)) 
                   AND (:loc_lat+(:radius/69))
           AND v.veh_status=:veh_status
      )

If we also need to return a row from the vehicle table, we can use aggregation in an inline view, and a JOIN . 如果还需要从vehicle表返回一行,则可以在内联视图中使用聚合,并在JOIN中使用。

 SELECT c.*
      , g.*
   FROM tbl_car_class_category c
   JOIN ( SELECT v.veh_class_id
               , MIN(v.id)    AS   min_id   -- PK or unique identifier    
            FROM tbl_vehicles v 
            AND v.veh_advanceLng 
                BETWEEN (:loc_long-:radius/cos(radians(:loc_lat))*69)
                    AND (:loc_long+:radius/cos(radians(:loc_lat))*69)
            AND v.veh_advanceLat
                BETWEEN (:loc_lat-(:radius/69)) 
                    AND (:loc_lat+(:radius/69))
            AND v.veh_status=:veh_status
          GROUP BY v.veh_class_id 
        ) m
     ON m.veh_class_id = c.id_class_cat
   JOIN tbl_vehicles g
     ON g.id           = m.min_id
    AND g.veh_class_id = m.veh_class_id
  ORDER BY ...

(NOTE: this assumes that id_class_cat is UNIQUE in tbl_car_class_category ) (注意:这假设id_class_cattbl_car_class_category是唯一的)

Have you tried LIMIT? 您尝试过LIMIT吗?

$get_veh = $pdo->prepare("SELECT * FROM tbl_car_class_category JOIN tbl_vehicles ON tbl_vehicles.veh_class_id = tbl_car_class_category.id_class_cat WHERE tbl_vehicles.veh_advanceLng between (:loc_long-:radius/cos(radians(:loc_lat))*69) and (:loc_long+:radius/cos(radians(:loc_lat))*69) and veh_advanceLat between (:loc_lat-(:radius/69)) and (:loc_lat+(:radius/69)) AND veh_status=:veh_status LIMIT 1");

http://www.mysqltutorial.org/mysql-limit.aspx http://www.mysqltutorial.org/mysql-limit.aspx

Or DISTINCT: https://dev.mysql.com/doc/refman/5.7/en/distinct-optimization.html 或DISTINCT: https : //dev.mysql.com/doc/refman/5.7/en/distinct-optimization.html

for get a single row for each class you can use a (fake eg: min) aggregation functio and group by 为了获得每个类的单行,您可以使用(假的:min)聚合函数并分组

( do the absence of the table schema assuming that you have col1, col2, col3 instead of * ) (在没有表模式的情况下,假设您使用col1,col2,col3而不是*)

$get_veh = $pdo->prepare("SELECT 
               tbl_car_class_category.id_class_cat
                    , min(col1)
                    , min(col2) 
                    , min(col3)
     FROM tbl_car_class_category 
     JOIN tbl_vehicles ON tbl_vehicles.veh_class_id = tbl_car_class_category.id_class_cat
     WHERE tbl_vehicles.veh_advanceLng between (:loc_long-:radius/cos(radians(:loc_lat))*69) 
                    and (:loc_long+:radius/cos(radians(:loc_lat))*69) 
                    and veh_advanceLat between (:loc_lat-(:radius/69)) 
                    and (:loc_lat+(:radius/69)) AND veh_status=:veh_status
                    GROUP BY tbl_car_class_category.id_class_cat");

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM