1

我当前的代码

SELECT post_id, ( 3959 * ACOS( COS( RADIANS( 34.09 ) ) * COS( RADIANS( lat ) ) * COS( RADIANS( lng ) - RADIANS( -117.55 ) ) + SIN( RADIANS( 34.09 ) ) * SIN( RADIANS( lat ) ) ) ) AS distance FROM wp_postmeta WHERE `meta_key` LIKE '%location_l%' HAVING distance < 2500 ORDER BY distance LIMIT 0 , 20

以下是两个示例数据行(meta_key 并不总是 long 或 lat):

post_id = 123  
meta_key = location_longitude  
meta_value = -119.890000  

post_id = 123  
meta_key = location_latitude   
meta_value = 42.170000

如何修改我的查询以将原始查询中的“lat”和“lng”替换为上面列出的 meta_value 的内容?像这样的东西?

select meta_value where meta_key = location_latitude
4

4 回答 4

1

如果你GROUP BY post_id,你应该能够使用MAX()聚合代替lat,lng, 周围的CASE语句来确定当前行是纬度还是经度。其他的将为 NULL,因此被聚合消除。

我认为这应该可行,因此您不需要任何子选择。

SELECT
   post_id, 
   ( 3959 * ACOS( COS( RADIANS( 34.09 ) ) * COS( RADIANS( MAX(CASE WHEN meta_key='location_latitude' THEN meta_value ELSE NULL END) ) ) * COS( RADIANS( MAX(CASE WHEN meta_key='location_longitude' THEN meta_value ELSE NULL END) ) - RADIANS( -117.55 ) ) + SIN( RADIANS( 34.09 ) ) * SIN( RADIANS( MAX(CASE WHEN meta_key='location_latitude' THEN meta_value ELSE NULL END) ) ) ) ) AS distance 
FROM wp_postmeta 
WHERE `meta_key` IN ('location_latitude','location_longitude')
GROUP BY post_id
HAVING distance < 2500 
ORDER BY distance 
LIMIT 0 , 20

这里的活动部分是:

MAX(CASE WHEN meta_key='location_latitude' THEN meta_value ELSE NULL END)

这翻译为:如果该行meta_key'location_latitude',则返回meta_value,否则返回 NULL。我们希望,由于post_id(lat,lng) 返回了两行,所以MAX()上面返回的值始终是非空值——来自 的正确纬度或经度值meta_value

于 2012-08-17T18:48:04.503 回答
1

FROM wp_postmeta一种方法是用内联视图替换查询中对表(即)的引用,如下所示:

FROM
( SELECT plat.post_id
       , plat.meta_value AS lat
       , plng.meta_value AS lng
    FROM wp_postmeta plat
    JOIN wp_postmeta plng
      ON plat.post_id = plng.post_id
         AND plat.meta_key = 'location_latitude'
         AND plng.meta_ley = 'location_longitude'
) wpm

(注意:这假设对于两个感兴趣的 meta_key 值中的每一个,每个 post_id 只有一行...)

这使用“内联视图”将每个 post_id 的纬度和经度值组合成一行。(您可以只运行对内联视图的查询,以确认它返回您期望的结果。)在更新的 MySQL 版本(版本 >= 5.0)中,我们可以使用内联视图代替表引用。

于 2012-08-17T18:51:33.090 回答
1

您需要将表连接到自身(这在具有 EAV 结构的数据库中很常见):

SELECT
    post_id,
    distance
FROM
  ( SELECT 
        lng.post_id, 
        ( 3959 * ACOS( COS( RADIANS( 34.09 ) ) 
                     * COS( RADIANS( lat.meta_value ) ) 
                     * COS( RADIANS( lng.meta_value ) 
                          - RADIANS( -117.55 ) ) 
                     + SIN( RADIANS( 34.09 ) ) 
                     * SIN( RADIANS( lat.meta_value ) ) 
                     ) 
        ) AS distance 
    FROM wp_postmeta AS lng
      JOIN wp_postmeta AS lat
        ON lat.post_id = lng.post_id
    WHERE lng.meta_key = 'location_longitude'
      AND lat.meta_key = 'location_latitude'
  ) AS tmp
WHERE distance < 2500 
ORDER BY distance 
  LIMIT 0 , 20 ;
于 2012-08-17T18:51:45.117 回答
0
SELECT a.post_id, 
  ( 3959 * ACOS( COS( RADIANS( 34.09 ) ) * COS( RADIANS( lat.meta_value  ) ) * COS( RADIANS( lng.meta_value  ) - RADIANS( -117.55 ) ) + SIN( RADIANS( 34.09 ) ) * SIN( RADIANS( lat.meta_value  ) ) ) ) AS distance 
FROM wp_postmeta lat, wp_postmeta lng
WHERE lat.post_id = lng.postID
AND lat.meta_key = 'location_latitude'
AND lng.meta_key = 'location_longitude'
HAVING distance < 2500 
ORDER BY distance LIMIT 0 , 20
于 2012-08-17T18:49:28.163 回答