Câu trả lời:
Hãy xem các kiểu dữ liệu Không gian mới đã được giới thiệu trong SQL Server 2008. Chúng được thiết kế cho loại tác vụ này và làm cho việc lập chỉ mục và truy vấn dễ dàng và hiệu quả hơn nhiều.
Thêm thông tin:
Cảnh báo đúng! Trước khi thực hiện lời khuyên sử dụng loại GEOGRAPHY, hãy đảm bảo rằng bạn không định sử dụng Linq hoặc Entity Framework để truy cập dữ liệu vì nó không được hỗ trợ (kể từ tháng 11 năm 2010) và bạn sẽ rất buồn!
Cập nhật tháng 7 năm 2017
Đối với những người đọc câu trả lời này bây giờ, nó đã lỗi thời vì nó ám chỉ ngăn xếp công nghệ lạc hậu. Xem bình luận để biết thêm chi tiết.
Tôi không biết câu trả lời cho SQL Server nhưng ...
Trong MySQL, hãy lưu nó dưới dạngFLOAT( 10, 6 )
Đây là khuyến nghị chính thức từ tài liệu dành cho nhà phát triển của Google .
CREATE TABLE `coords` (
`lat` FLOAT( 10, 6 ) NOT NULL ,
`lng` FLOAT( 10, 6 ) NOT NULL ,
) ENGINE = MYISAM ;
lat
và hoạt động lng
tốt hơn georgraphy
, ngay cả với các chỉ số mật độ cao trong SQL 2014. Ví dụ: find all point is witering một hình chữ nhật. Chỉ có điều tôi không rõ, tôi thấy Google Maps bây giờ sử dụng chữ số 7 thay vì 6 chữ số?
Cách tôi làm điều đó: Tôi lưu trữ vĩ độ và kinh độ và sau đó tôi có cột thứ ba là loại địa lý tự động có nguồn gốc từ hai cột đầu tiên. Bảng trông như thế này:
CREATE TABLE [dbo].[Geopoint]
(
[GeopointId] BIGINT NOT NULL PRIMARY KEY IDENTITY,
[Latitude] float NOT NULL,
[Longitude] float NOT NULL,
[ts] ROWVERSION NOT NULL,
[GeographyPoint] AS ([geography]::STGeomFromText(((('POINT('+CONVERT([varchar](20),[Longitude]))+' ')+CONVERT([varchar](20),[Latitude]))+')',(4326)))
)
Điều này mang lại cho bạn sự linh hoạt của các truy vấn không gian trên cột geoPoint và bạn cũng có thể truy xuất các giá trị vĩ độ và kinh độ khi bạn cần để hiển thị hoặc trích xuất cho mục đích csv.
Point
thay vì STGeomFromText
. Ví dụ: [geography]::Point([Latitude], [Longitude], 4326)
.
Tôi ghét phải đối nghịch với những người đã nói "đây là một loại mới, chúng ta hãy sử dụng nó". Các kiểu không gian SQL Server 2008 mới có một số ưu điểm - cụ thể là hiệu quả, tuy nhiên bạn không thể nói một cách mù quáng là luôn sử dụng kiểu đó. Nó thực sự phụ thuộc vào một số vấn đề hình ảnh lớn hơn.
Như một ví dụ, tích hợp. Loại này có một loại tương đương trong .Net - nhưng còn interop thì sao? Điều gì về việc hỗ trợ hoặc mở rộng các phiên bản cũ hơn của .Net? Điều gì về việc hiển thị loại này trên lớp dịch vụ cho các nền tảng khác? Còn về việc chuẩn hóa dữ liệu - có thể bạn quan tâm đến các phần thông tin độc lập về vĩ độ hoặc lâu dài. Có lẽ bạn đã viết logic nghiệp vụ phức tạp để xử lý long / lat.
Tôi không nói rằng bạn không nên sử dụng kiểu không gian - trong nhiều trường hợp, bạn nên làm như vậy. Tôi chỉ nói rằng bạn nên hỏi một số câu hỏi quan trọng hơn trước khi đi xuống con đường đó. Để tôi trả lời câu hỏi của bạn chính xác nhất, tôi cần biết thêm về tình hình cụ thể của bạn.
Lưu trữ dài / vĩ độ riêng biệt hoặc trong một kiểu không gian đều là những giải pháp khả thi và cách này có thể phù hợp hơn với cách khác tùy thuộc vào hoàn cảnh của riêng bạn.
Những gì bạn muốn làm là lưu trữ Vĩ độ và Kinh độ ở dạng SQL2008 Spatial mới -> GEOGRAPHY.
Đây là ảnh chụp màn hình của một cái bàn mà tôi có.
văn bản thay thế http://img20.imageshack.us/img20/6839/zipcodetable.png
Trong bảng này, chúng ta có hai trường lưu trữ dữ liệu địa lý.
Lý do chính khiến bạn muốn lưu nó vào cơ sở dữ liệu dưới dạng kiểu GEOGRAPHY là vì vậy bạn có thể tận dụng tất cả các phương thức SPATIAL từ nó -> ví dụ: Điểm trong Poly, Khoảng cách giữa hai điểm, v.v.
BTW, chúng tôi cũng sử dụng API Maps của Google để truy xuất dữ liệu vĩ độ / dài và lưu trữ dữ liệu đó trong Sql 2008 DB của chúng tôi - vì vậy phương pháp này hoạt động.
SQL Server có hỗ trợ thông tin liên quan đến không gian. Bạn có thể xem thêm tại http://www.microsoft.com/sqlserver/2008/en/us/spatial-data.aspx .
Ngoài ra, bạn có thể lưu trữ thông tin dưới dạng hai trường cơ bản, thường float là loại dữ liệu tiêu chuẩn được hầu hết các thiết bị báo cáo và đủ chính xác trong phạm vi một hoặc hai inch - quá đủ cho Google Maps.
LƯU Ý : Đây là câu trả lời gần đây dựa trên máy chủ SQL gần đây, các bản cập nhật ngăn xếp .NET
vĩ độ và kinh độ từ Google Maps nên được lưu trữ dưới dạng dữ liệu Điểm (ghi chú viết hoa P) trong máy chủ SQL theo kiểu dữ liệu địa lý.
Giả sử dữ liệu hiện tại của bạn được lưu trữ trong một bảng Sample
dưới dạng varchar dưới các cột lat
và lon
truy vấn bên dưới sẽ giúp bạn chuyển đổi sang vị trí địa lý
alter table Sample add latlong geography
go
update Sample set latlong= geography::Point(lat,lon,4326)
go
Tái bút: Lần tới khi bạn chọn trên bảng này với dữ liệu địa lý, ngoài tab Kết quả và Tin nhắn, bạn cũng sẽ nhận được tab Kết quả không gian như bên dưới để hình dung
Nếu bạn đang sử dụng Entity Framework 5 <bạn có thể sử dụng DbGeography
. Ví dụ từ MSDN:
public class University
{
public int UniversityID { get; set; }
public string Name { get; set; }
public DbGeography Location { get; set; }
}
public partial class UniversityContext : DbContext
{
public DbSet<University> Universities { get; set; }
}
using (var context = new UniversityContext ())
{
context.Universities.Add(new University()
{
Name = "Graphic Design Institute",
Location = DbGeography.FromText("POINT(-122.336106 47.605049)"),
});
context. Universities.Add(new University()
{
Name = "School of Fine Art",
Location = DbGeography.FromText("POINT(-122.335197 47.646711)"),
});
context.SaveChanges();
var myLocation = DbGeography.FromText("POINT(-122.296623 47.640405)");
var university = (from u in context.Universities
orderby u.Location.Distance(myLocation)
select u).FirstOrDefault();
Console.WriteLine(
"The closest University to you is: {0}.",
university.Name);
}
https://msdn.microsoft.com/en-us/library/hh859721(v=vs.113).aspx
Một cái gì đó tôi đã đấu tranh với sau đó tôi bắt đầu sử dụng DbGeography
là coordinateSystemId
. Xem câu trả lời bên dưới để có lời giải thích tuyệt vời và nguồn cho mã bên dưới.
public class GeoHelper
{
public const int SridGoogleMaps = 4326;
public const int SridCustomMap = 3857;
public static DbGeography FromLatLng(double lat, double lng)
{
return DbGeography.PointFromText(
"POINT("
+ lng.ToString() + " "
+ lat.ToString() + ")",
SridGoogleMaps);
}
}
Nếu bạn chỉ định thay thế nó thành một URL, tôi cho rằng một trường sẽ làm được - vì vậy bạn có thể tạo một URL như
http://maps.google.co.uk/maps?q=12.345678,12.345678&z=6
nhưng vì nó là hai phần dữ liệu nên tôi sẽ lưu trữ chúng trong các trường riêng biệt
Lưu trữ cả hai dưới dạng float và sử dụng các từ khóa duy nhất trên chúng. I.em
create table coordinates(
coord_uid counter primary key,
latitude float,
longitude float,
constraint la_long unique(latitude, longitude)
);
House A
và sẽ chuyển đến House B
, ngôi nhà nơi Alice từng sống. Chẳng bao lâu nữa Bob sẽ không thể lưu địa chỉ (vị trí) của mình, vì Alice chưa cập nhật địa chỉ của cô ấy - hoặc sẽ không bao giờ.