Hãy xem một ví dụ đơn giản về việc sử dụng STDistance
trong SQL Server 2008 (và mới hơn).
Tôi sẽ nói với SQL Server rằng tôi đang ở London và tôi muốn xem khoảng cách của từng văn phòng của tôi. Đây là kết quả mà tôi muốn SQL Server cung cấp cho tôi:
Đầu tiên, chúng tôi sẽ cần một số dữ liệu mẫu. Chúng tôi sẽ tạo một bảng chứa một vài vị trí của các văn phòng Microsoft và chúng tôi sẽ lưu trữ các giá trị kinh độ &vĩ độ của chúng trong một geography
trường.
CREATE TABLE [Offices] (
[Office_Id] [int] IDENTITY(1, 1) NOT NULL,
[Office_Name] [nvarchar](200) NOT NULL,
[Office_Location] [geography] NOT NULL,
[Update_By] nvarchar(30) NULL,
[Update_Time] [datetime]
) ON [PRIMARY]
GO
INSERT INTO [dbo].[Offices] VALUES ('Microsoft Zurich', 'POINT(8.590847 47.408860 )', 'mike', GetDate())
INSERT INTO [dbo].[Offices] VALUES ('Microsoft San Francisco', 'POINT(-122.403697 37.792062 )', 'mike', GetDate())
INSERT INTO [dbo].[Offices] VALUES ('Microsoft Paris', 'POINT(2.265509 48.833946)', 'mike', GetDate())
INSERT INTO [dbo].[Offices] VALUES ('Microsoft Sydney', 'POINT(151.138378 -33.796572)', 'mike', GetDate())
INSERT INTO [dbo].[Offices] VALUES ('Microsoft Dubai', 'POINT(55.286282 25.228850)', 'mike', GetDate())
Bây giờ, giả sử chúng tôi đang ở London. Đây là cách tạo geography
giá trị ngoài các giá trị kinh độ &vĩ độ của Luân Đôn:
DECLARE
@latitude numeric(12, 7),
@longitude numeric(12, 7)
SET @latitude = 51.507351
SET @longitude = -0.127758
DECLARE @g geography = 'POINT(' + cast(@longitude as nvarchar) + ' ' + cast(@latitude as nvarchar) + ')';
Và cuối cùng, hãy xem mỗi văn phòng của chúng ta cách nhau bao xa.
SELECT [Office_Name],
cast([Office_Location].STDistance(@g) / 1609.344 as numeric(10, 1)) as 'Distance (in miles)'
FROM [Offices]
ORDER BY 2 ASC
Và điều này mang lại cho chúng tôi kết quả mà chúng tôi mong đợi.
Rõ ràng, bạn có thể trượt TOP(1)
nếu bạn chỉ muốn xem gần nhất văn phòng.
Hay quá, này?
Chỉ có một sự cố. Khi bạn có nhiều geography
điểm để so sánh, hiệu suất không xuất sắc, ngay cả khi bạn thêm CHỈ SỐ SPATIAL trên trường cơ sở dữ liệu đó.
Tôi đã kiểm tra một điểm dựa trên bảng 330.000 geography
điểm. Sử dụng mã hiển thị ở đây, nó tìm thấy điểm gần nhất trong khoảng 8 giây .
Khi tôi sửa đổi bảng của mình để lưu trữ các giá trị kinh độ và vĩ độ, đồng thời sử dụng [dbo].[fnCalcDistanceMiles]
từ bài viết StackOverflow này, nó đã tìm thấy điểm gần nhất trong khoảng 3 giây .
Tuy nhiên ...
Tất cả các mẫu "khoảng cách giữa hai điểm" mà tôi tìm thấy trên internet đều sử dụng SQL Server STDistance
hàm hoặc các công thức toán học liên quan đến các hàm cos, sin và tan (sử dụng nhiều CPU).
Một giải pháp nhanh hơn là quay ngược thời gian trở lại thời trung học và nhớ cách Pythagoras tính khoảng cách giữa hai điểm.
Giả sử chúng tôi muốn biết khoảng cách giữa London và Paris.
Và đây là hàm SQL Server của tôi:
CREATE FUNCTION [dbo].[uf_CalculateDistance] (@Lat1 decimal(8,4), @Long1 decimal(8,4), @Lat2 decimal(8,4), @Long2 decimal(8,4))
RETURNS decimal (8,4) AS
BEGIN
DECLARE @d decimal(28,10)
SET @d = sqrt(square(@[email protected]) + square(@[email protected]))
RETURN @d
END
Bây giờ, hãy nhớ rằng hàm này không trả về giá trị theo dặm, km, v.v. ... mà chỉ là so sánh các giá trị kinh độ &vĩ độ. Và Pythagoras được dùng trong 2D chứ không phải so sánh các điểm trên một hành tinh tròn!
Tuy nhiên, trong các thử nghiệm của tôi, nó đã tìm thấy điểm gần nhất trong vòng 1 giây và tạo ra kết quả tương tự như khi sử dụng STDistance
của SQL Server chức năng.
Vì vậy, vui lòng sử dụng chức năng này để so sánh khoảng cách tương đối , nhưng không sử dụng chức năng này nếu bạn cần khoảng cách thực tế.
Hy vọng tất cả điều này sẽ hữu ích.