1

私は次のテーブルと関係を持っています:

Players:
foreign_key to User  

Users:
foreign_key to City

Cities:
latitude (float)
longitude (float)

ユーザーに関連付けられているすべての教授を特定の都市またはnear_by都市から取得しようとしています。

このクエリを使用すると、特定の緯度と経度が指定されたnear_by(20km)の都市と、指定された都市の緯度と経度までの距離が返されます。この場合latitude = 41.353312 and longitude = 1.976252

SELECT cities.*,
 6371 *
 acos(cos(radians(41.353312)) *
 cos(radians(cities.latitude)) *
 cos(radians(cities.longitude) - radians(1.976252)) +
 sin(radians(41.353312))*sin(radians(cities.latitude)))
 AS km_away FROM `cities` GROUP BY km_away ASC HAVING km_away <= 20

そして、このクエリ(機能しません)を試しました。これにより、ユーザーの都市が指定された都市(緯度と経度)の近くにあるプレーヤーを返すことができます。

SELECT COUNT(*) 
FROM `players` 
INNER JOIN `users` 
    ON `users`.`id` = `players`.`user_id` 
INNER JOIN `cities` 
    ON `cities`.`id` = `users`.`city_id`
WHERE 
(
    cities.id IN 
     (SELECT cities.*,
             6371 *
             acos(cos(radians(41.353312)) *
             cos(radians(cities.latitude)) *
             cos(radians(cities.longitude) - radians(1.976252)) +
             sin(radians(41.353312))*sin(radians(cities.latitude))) AS km_away 
        FROM `cities` 
        GROUP BY km_away ASC 
        HAVING km_away <= 20)
)

私もしたい:

1-関連するユーザー都市から特定の都市までの距離順にプレーヤーを並べ替えます。

2-返された各レコードの距離(値)を取得します。

4

2 に答える 2

2

どの結果セットを返したいのか完全にはわかりません。しかし、あなたの問題を見ると、サブクエリ(バルセロナからの距離の「大円距離」の計算には+1!)をロウソースとして使用したいと思います。

1 つの方法は、サブクエリを WHERE 句で参照するのではなく、「インライン ビュー」として使用することです。

そのクエリは、citys テーブルからすべての列を返すため、基本的にクエリ内のcitys テーブルを置き換えることができます。

GROUP BY 句は必要ありません。2 つの都市が指定された緯度/経度から等距離にある場合にのみ、結果セットから行を削除するのに役立ちます。(それがあなたの望む振る舞いだとは思いません。それを望むのは間違いではありませんが、非常に珍しいことです。)

SELECT COUNT(*) 
FROM `players` 
INNER JOIN `users` 
    ON `users`.`id` = `players`.`user_id` 
INNER JOIN 
 (SELECT cities.*,
         6371 *
         acos(cos(radians(41.353312)) *
         cos(radians(cities.latitude)) *
         cos(radians(cities.longitude) - radians(1.976252)) +
         sin(radians(41.353312))*sin(radians(cities.latitude))) AS km_away 
    FROM `cities` 
    HAVING km_away <= 20
    ORDER BY km_away
 ) `cd` 
    ON `cd`.`id` = `users`.`city_id`

注: そのインライン ビューにエイリアスを付けましたcd(これは、都市の距離の省略形として読みます。

COUNT 集計は 1 行のみを返すため、ORDER BY は必要ありません。SELECT リストを変更し、行を特定の順序で返す場合は、最も外側のクエリに ORDER BY を追加します。

ORDER BY cd.km_away ASC

アップデート:

citiesplayers、テーブルの任意の列、およびSELECT リストでusers計算された距離 ( )を参照できるはずです。km_awayもちろん、「.*」を使用するのではなく、返される列を指定します。ただし、「cd.km_away」は外部クエリ (SELECT リスト、WHERE 句、ORDER BY など) で参照できます。

SELECT cd.km_away
     , cd.*
     , players.*
     , users.*
FROM `players` 
INNER JOIN `users` 
    ON `users`.`id` = `players`.`user_id` 
INNER JOIN 
 (SELECT cities.*,
         6371 *
         acos(cos(radians(41.353312)) *
         cos(radians(cities.latitude)) *
         cos(radians(cities.longitude) - radians(1.976252)) +
         sin(radians(41.353312))*sin(radians(cities.latitude))) AS km_away 
    FROM `cities` 
    HAVING km_away <= 20
    ORDER BY km_away
 ) `cd` 
    ON `cd`.`id` = `users`.`city_id`
 ORDER BY cd.km_away
于 2012-07-20T21:09:32.400 に答える
1

GROUP BY 句で ASC を取得しました。ORDER BY を使用することを意味します。

編集 mysql についての私の無知を許してください。私は標準的なアプローチに固執することを好みます。特に、それらが最も簡単なアプローチでもある場合はなおさらです。OPは「うまくいかない」と太字で指摘し、質問全体を読む前に、私の回答の元の回答が問題である可能性が高いと信じていました。

SELECT
    6371 *
    acos(cos(radians(41.353312)) *
    cos(radians(cities.latitude)) *
    cos(radians(cities.longitude) - radians(1.976252)) +
    sin(radians(41.353312))*sin(radians(cities.latitude))) as km,
    ...
FROM
    players
    INNER JOIN users ON users.id = players. user_id
    INNER JOIN cities ON cities.id = users.city_id
WHERE 
    6371 *
    acos(cos(radians(41.353312)) *
    cos(radians(cities.latitude)) *
    cos(radians(cities.longitude) - radians(1.976252)) +
    sin(radians(41.353312))*sin(radians(cities.latitude)))
    <= 20
ORDER BY
    6371 *
    acos(cos(radians(41.353312)) *
    cos(radians(cities.latitude)) *
    cos(radians(cities.longitude) - radians(1.976252)) +
    sin(radians(41.353312))*sin(radians(cities.latitude)))
    ASC

派生テーブル/仮想テーブル/インライン ビューは、それを少しクリーンアップします。

SELECT cities.km, ...
FROM
    players
    INNER JOIN users ON users.id = players. user_id
    INNER JOIN
        (
        SELECT
            cities.*, /* don't know if this works on mysql */
            6371 *
            acos(cos(radians(41.353312)) *
            cos(radians(cities.latitude)) *
            cos(radians(cities.longitude) - radians(1.976252)) +
            sin(radians(41.353312))*sin(radians(cities.latitude))) as km
        ) as cities /* maybe another name is appropriate */
        ON cities.id = users.city_id
WHERE cities.km <= 20
ORDER BY cities.km ASC
于 2012-07-20T20:27:39.530 に答える