Bạn chỉ cần thực hiện tự tham gia. Tham gia bảng là một rất phần cơ bản của SQL — bạn thực sự nên đọc kỹ trước khi cố gắng hiểu thêm câu trả lời này.
SELECT poi.asciiname,
suburb.asciiname,
suburb.country,
DEGREES(
ACOS(
SIN(RADIANS( poi.latitude))
* SIN(RADIANS(suburb.latitude))
+ COS(RADIANS( poi.latitude))
* COS(RADIANS(suburb.latitude))
* COS(RADIANS(poi.longitude - suburb.longitude))
)
) * 60 * 1.852 AS distance
FROM geoname AS poi
JOIN geoname AS suburb
WHERE poi.asciiname IN ('Tamworth', 'Birmingham', 'Roanoke')
AND poi.population > 0
AND poi.fcode = 'PPL'
AND suburb.fcode IN ('PPLX', 'PPPL')
HAVING distance <= 60
ORDER BY poi.asciiname, distance
Xem nó trên sqlfiddle .
Bạn sẽ nhận thấy rằng tôi đã sử dụng IN()
toán tử dưới dạng viết tắt cho value = A OR value = B OR ...
.
Bạn cũng sẽ nhận thấy rằng tôi đã sử dụng DEGREES()
và RADIANS()
thay vì cố gắng thực hiện các chuyển đổi như vậy một cách rõ ràng.
Sau đó, bạn đang nhân phút vĩ độ với hệ số của 1.851999999962112
, khá lạ:nó cực kỳ gần với 1.852
, là số km chính xác trong một hải lý (theo lịch sử được định nghĩa là một phút vĩ độ), nhưng hơi khác một cách kỳ lạ — tôi cho rằng bạn muốn sử dụng số đó để thay thế.
Cuối cùng, bạn đã có giá trị theo nghĩa đen mà bạn đang lọc các khoảng cách trong tập kết quả dưới dạng một chuỗi, tức là '60'
, trong khi rõ ràng đây là một giá trị số và không được trích dẫn.