0

このクエリは私を狂気に駆り立てており、正直なところ、それを達成する方法がわかりません。

特定の半径内にあるすべての USERS と SHOPS の経度と緯度を取得し、それらの結果の ID に添付された他の情報を返す必要があります...半径の部分については、次のことがわかりました。

( 3959 * acos( cos( radians('48.453541') ) * cos( radians( lat ) ) * cos( radians( lng ) - radians('-123.491765') ) + sin( radians('48.453541') ) * sin( radians( lat ) ) ) ) AS distance

^上記のステートメントのこのラジアンは、照会したいランダムなアドレスです。

しかし、本質的に 2 つの異なる行を 1 つの結果として取得すると、すぐに混乱してしまいます。両方のテーブルは、次の方法で作成されます。

id
meta_key
meta_value

したがって、USER と SHOP の両方の 2 つのキーの「meta_value」を取得する必要があります...USER の「meta_key」は「bid_user_lat」と「bid_user_lng」です...SHOP の「meta_key」は「 bid_resource_lat」と「bid_resource_lng」

理想的な結果 (それぞれを 1 つだけ表示しますが、半径に応じて複数にする必要があります):

id - 223
first_name - "Mark"
last_name - "Johnson"
bid_user_lat - 45.0000
bid_user_lng - -150.0000

id - 688
company_name - "Joe's Shop"
bid_resource_lat - 45.0000
bid_resource_lng - -150.0000

これは私を夢中にさせているだけなので、これを正しく説明していることを本当に願っています!


私の更新されたクエリは次のとおりですが、それでも結果は生成されず、次のようになります。

SET @lat =  '48.453541';
SET @lng =  '-123.491765';
SET @radius =  '10000';

SELECT
    wp_usermeta.user_id,
    bid_user_lat.meta_value,
    bid_user_lng.meta_value,

( 3959 * acos( cos( radians( @lat ) ) * cos( radians( bid_user_lat.meta_value ) ) * cos( radians( bid_user_lng.meta_value ) - radians( @lng ) ) + sin( radians( @lat ) ) * sin( radians( bid_user_lat.meta_value ) ) ) )  AS distance 

FROM
    wp_usermeta
JOIN 
    wp_usermeta bid_user_lat
    ON wp_usermeta.user_id = bid_user_lat.user_id
    AND wp_usermeta.meta_key = "bid_user_lat"
JOIN
    wp_usermeta bid_user_lng
    ON wp_usermeta.user_id = bid_user_lng.user_id
    AND wp_usermeta.meta_key = "bid_user_lng"

HAVING distance < @radius ORDER BY distance LIMIT 0 , 20;
4

1 に答える 1

0

この情報は、自己結合を使用して取得できます。

SELECT
    table.id,
    bid_user_lat.meta_value,
    bid_user_lng.meta_value
FROM
    table
JOIN 
    table bid_user_lat
    ON table.id = bid_user_lat.id
    AND table.meta_key = "bid_user_lat"
JOIN
    table bid_user_lng
    ON table.id = bid_user_lng.id
    AND table.meta_key = "bid_user_lng"
WHERE
    { distance clause }

...距離句は、適切な距離内にあることを確認する場所です。値として、および計算の値bid_user_lat.meta_valueとして使用できます。bid_user_latbid_user_lng.meta_valuebid_user_lng

User の結果を Shop の結果と同じクエリで返したい場合は、上記と同じクエリを実行し (もちろん、Users の代わりに Shops を使用します)、それらをUNIONまたはで接続しますUNION ALL

サイドノート:

データベースを制御できる場合は、設計を再確認することをお勧めします。上記の解決策は決して理想的ではありません... ユーザーが常にbid_user_latフィールドとbid_user_lngフィールドを持っている場合、またはそれがユーザーの共通属性である場合でも、ユーザーテーブルに独自の列が必要です。

修正:

私はJOIN間違っていました。ON節はのbid_user_lng.meta_key = "bid_user_lat"代わりに使用する必要がありwp_usermeta.meta_key = "bid_user_lat"ます。GROUP BYまた、レコードが重複しないように句を追加する必要があります。これらを上記のクエリに適用すると、次のようになります。

SET @lat =  '48.453541';
SET @lng =  '-123.491765';
SET @radius =  '10000';

SELECT
    wp_usermeta.user_id,
    bid_user_lat.meta_value,
    bid_user_lng.meta_value,

( 3959 * acos( cos( radians( @lat ) ) * cos( radians( bid_user_lat.meta_value ) ) * cos( radians( bid_user_lng.meta_value ) - radians( @lng ) ) + sin( radians( @lat ) ) * sin( radians( bid_user_lat.meta_value ) ) ) )  AS distance 

FROM
    wp_usermeta
JOIN 
    wp_usermeta bid_user_lat
    ON wp_usermeta.user_id = bid_user_lat.user_id
    AND bid_user_lat.meta_key = "bid_user_lat"
JOIN
    wp_usermeta bid_user_lng
    ON wp_usermeta.user_id = bid_user_lng.user_id
    AND bid_user_lng.meta_key = "bid_user_lng"

GROUP BY wp_usermeta.user_id

HAVING distance < @radius ORDER BY distance LIMIT 0 , 20;

これが機能することの確認は次のとおりです。

mysql> CREATE TABLE wp_usermeta (user_id INTEGER UNSIGNED, meta_key VARCHAR(255), meta_value VARCHAR(255));
Query OK, 0 rows affected (0.25 sec)

mysql> INSERT INTO wp_usermeta (user_id, meta_key, meta_value)
    -> VALUES
    -> (1, "bid_user_lat", "45.000"), (1, "bid_user_lng", "-150.000"),
    -> (2, "bid_user_lat", "20.000"), (2, "bid_user_lng", "20.000"),
    -> (3, "bid_user_lat", "-300.000"), (3, "bid_user_lng", "70.000");
Query OK, 6 rows affected (0.16 sec)
Records: 6  Duplicates: 0  Warnings: 0

mysql> SELECT
    ->     wp_usermeta.user_id,
    ->     bid_user_lat.meta_value,
    ->     bid_user_lng.meta_value,
    -> 
    -> ( 3959 * acos( cos( radians( @lat ) ) * cos( radians( bid_user_lat.meta_value ) ) * cos( radians( bid_user_lng.meta_value ) - radians( @lng ) ) + sin( radians( @lat ) ) * sin( radians( bid_user_lat.meta_value ) ) ) )  AS distance 
    -> 
    -> FROM
    ->     wp_usermeta
    -> JOIN 
    ->     wp_usermeta bid_user_lat
    ->     ON wp_usermeta.user_id = bid_user_lat.user_id
    ->     AND bid_user_lat.meta_key = "bid_user_lat"
    -> JOIN
    ->     wp_usermeta bid_user_lng
    ->     ON wp_usermeta.user_id = bid_user_lng.user_id
    ->     AND bid_user_lng.meta_key = "bid_user_lng"
    -> 
    -> GROUP BY wp_usermeta.user_id
    -> 
    -> HAVING distance < @radius ORDER BY distance LIMIT 0 , 20;
+---------+------------+------------+--------------------+
| user_id | meta_value | meta_value | distance           |
+---------+------------+------------+--------------------+
|       1 | 45.000     | -150.000   | 1271.3329043047352 |
|       3 | -300.000   | 70.000     | 4905.4310014631055 |
|       2 | 20.000     | 20.000     |  7198.549954690863 |
+---------+------------+------------+--------------------+
3 rows in set (0.05 sec)
于 2012-10-18T01:23:49.987 に答える