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

データの2つのサンプル行を次に示します(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を使用できるはずです。その他はNULLになるため、集計によって削除されます。 MAX()lat,lngCASE

これはうまくいくはずなので、副選択は必要ありません。

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)に対して2つの行が返されるため、MAX()上記で返される値は常にnull以外の値、つまりからの正しい緯度または経度の値であると予想されmeta_valueます。

于 2012-08-17T18:48:04.503 に答える
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

(注:これは、対象の2つのmeta_key値のそれぞれのpost_idごとに1つの行しかないことを前提としています...)

これは、「インラインビュー」を使用して、各post_idの緯度と経度の値を1つの行に結合します。(インラインビューのクエリだけを実行して、期待する結果が返されることを確認できます。)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 に答える