我当前的代码
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
答案 0 :(得分: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()
值始终为非空值 - 来自{{1的正确纬度或经度值}}
答案 1 :(得分: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
(注意:这假设每个post_id只有一行用于感兴趣的两个meta_key值...)
这使用“内联视图”将每个post_id的纬度和经度值组合成一行。 (您可以只运行内联视图的查询以确认它返回您期望的结果。)在更新版本的MySQL(版本&gt; = 5.0)中,我们可以使用内联视图代替表引用。
答案 2 :(得分: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 ;
答案 3 :(得分: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