SQL:复杂的Select语句和返回的半径

时间:2012-10-18 01:08:34

标签: mysql sql metadata

这个问题让我感到疯狂,老实说我只是不知道如何实现它。

我需要抓住所有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

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

但抓住结果本质上是两个不同的行AS ONE结果让我感到困惑。这两个表都是以这种方式构建的:

id
meta_key
meta_value

所以我需要为USER和SHOP获取两个键的“meta_value”... USER的“meta_key”是“bid_user_lat”和“bid_user_lng”...以及“meta_key” SHOP是“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;

1 个答案:

答案 0 :(得分: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值。

如果您想要返回与“结果”相同的查询中的“用户”结果,那么您可以执行与上述查询相同的查询(当然,使用“商店”而不是“用户”),并将其与{{1 }或UNION

旁注:

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

校正:

UNION ALL错了。 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;