0

这个查询让我发疯,老实说,我只是不知道如何完成它。

我需要获取某个半径内的所有用户和商店经度和纬度,并返回附加到这些结果 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

^上面语句中的这个弧度只是我要查询的随机地址。

但是抓取本质上是两个不同行的结果作为一个结果让我很困惑。这两个表都是以这种方式构造的:

id
meta_key
meta_value

所以我需要为 USER 和 SHOP 获取两个键的“meta_value”......用户的“meta_key”是“bid_user_lat”和“bid_user_lng”......而 SHOP 的“meta_key”是“ bid_resource_lat”和“bid_resource_lng”

理想的结果(只显示一个,但应该是多个,取决于半径):

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_lat值,也可以bid_user_lng.meta_value用作bid_user_lng计算中的值。

如果您想在与 Shop 结果相同的查询中返回 User 结果,那么您可以执行与上述查询相同的查询(当然使用 Shops 而不是 Users),并使用UNIONor连接它们UNION ALL

边注:

如果您对数据库有任何控制权,您可能需要重新访问该设计。上面的解决方案无论如何都不理想......如果一个用户总是有一个bid_user_lat和一个bid_user_lng字段,或者即使它只是用户的一个公共属性,那么它真的应该在用户表中有自己的列。

更正:

JOINing 不正确。该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 回答