15

ストアド プロシージャを作成しようとしています。これが私がこれまでに持っているものです(機能していません):

DELIMITER |
CREATE PROCEDURE getNearestCities(IN cityID INT)
    BEGIN
        DECLARE cityLat FLOAT;
        DECLARE cityLng FLOAT;
        SET cityLat = SELECT cities.lat FROM cities WHERE cities.id = cityID;
        SET cityLng = SELECT cities.lng FROM cities WHERE cities.id = cityID;
        SELECT *, HAVERSINE(cityLat,cityLng, cities.lat, cities.lng) AS dist FROM cities ORDER BY dist LIMIT 10;
    END |

HAVERSINE は私が作成した関数で、正常に動作します。ご覧のとおり、都市テーブルから都市の ID を取得し、cityLat と cityLng をそのレコードの他の値に設定しようとしています。ここでSELECTを使用することで、明らかにこれを間違っています。

これは可能ですか?そうあるべきだと思われます。どんな助けでも大歓迎です。

4

3 に答える 3

21

いくつかの点を修正し、代替の選択を追加しました - 必要に応じて削除します。

DELIMITER |

CREATE PROCEDURE getNearestCities
(
IN p_cityID INT -- should this be int unsigned ?
)
BEGIN

DECLARE cityLat FLOAT; -- should these be decimals ?
DECLARE cityLng FLOAT;

    -- method 1
    SELECT lat,lng into cityLat, cityLng FROM cities WHERE cities.cityID = p_cityID;

    SELECT 
     b.*, 
     HAVERSINE(cityLat,cityLng, b.lat, b.lng) AS dist 
    FROM 
     cities b 
    ORDER BY 
     dist 
    LIMIT 10;

    -- method 2
    SELECT   
      b.*, 
      HAVERSINE(a.lat, a.lng, b.lat, b.lng) AS dist
    FROM     
      cities AS a
    JOIN cities AS b on a.cityID = p_cityID
    ORDER BY 
      dist
    LIMIT 10;

END |

delimiter ;
于 2012-05-18T09:47:38.390 に答える
18

SELECTサブクエリであることを示すために、ステートメントを括弧で囲む必要があります。

SET cityLat = (SELECT cities.lat FROM cities WHERE cities.id = cityID);

または、MySQL のSELECT ... INTO構文を使用できます。このアプローチの利点の 1 つは、1 つのテーブル アクセスから と の両方cityLatcityLng割り当てることができることです。

SELECT lat, lng INTO cityLat, cityLng FROM cities WHERE id = cityID;

ただし、プロシージャ全体を単一の自己結合SELECTステートメントに置き換えることができます。

SELECT   b.*, HAVERSINE(a.lat, a.lng, b.lat, b.lng) AS dist
FROM     cities AS a, cities AS b
WHERE    a.id = cityID
ORDER BY dist
LIMIT    10;
于 2012-05-18T09:12:59.073 に答える