我有一个带Dapper的WebApi项目,我有表产品:
[Key]
public int idProducts { get; set; }
public string Name { get; set; }
public float Latitude { get; set; }
public float Longitude { get; set; }
public int ProductsItems { get; set; }
public decimal Price { get; set; }
我需要计算从A点到B点的距离并检查是否小于1km我已经做过,但在C#中
private static double distance(double lat1, double lon1, double lat2, double lon2, char unit)
{
double theta = lon1 - lon2;
double dist = Math.Sin(deg2rad(lat1)) *
Math.Sin(deg2rad(lat2)) +
Math.Cos(deg2rad(lat1)) *
Math.Cos(deg2rad(lat2)) *
Math.Cos(deg2rad(theta));
dist = Math.Acos(dist);
dist = rad2deg(dist);
dist = dist * 60 * 1.1515;
dist = dist * 1.609344;
return (dist);
}
private static double deg2rad(double deg)
{
return (deg * Math.PI / 180.0);
}
private static double rad2deg(double rad)
{
return (rad / Math.PI * 180.0);
}
bool isLess = distance(-8.157908, -34.931675, -8.164891, -34.919033, 'K') < 1
但是这样我必须做select * from Products
,获得所有结果AsList()
并制作一个循环来获取每个项目并检查从A到B的距离是否有效且不实用!我不习惯使用Math Involved进行这些查询。
如何创建一个查询,我可以从A点传递Lat和Long并进行数学运算并返回有效项目列表?
答案 0 :(得分:3)
您可以在SQL Server中使用GEOGRAPHY
。
示例强>
Declare @YourTable table (ID int,Lat float,Lng float)
Insert Into @YourTable values
(1,-8.157908, -34.931675)
,(2,-8.164891, -34.919033) -- Will be exclued ... 1,592 meters away
,(3,-8.159999, -34.939999) -- Forced to be < 1000 meters
DECLARE @Origin GEOGRAPHY
DECLARE @Fetch int = 1
Select @Origin =GEOGRAPHY::Point([Lat], [Lng], 4326) from @YourTable WHERE ID=@Fetch
Select *
,Meters = @Origin.STDistance(GEOGRAPHY::Point([Lat], [Lng], 4326))
From @YourTable
Where @Origin.STDistance(GEOGRAPHY::Point([Lat], [Lng], 4326)) <= 1000
Order By Meters
<强>返回强>
ID Lat Lng Meters
1 -8.157908 -34.931675 0 --<< Orgin/Fetch
3 -8.159999 -34.939999 946.007737339573
编辑 - 如果您想创建自己的计算
CREATE Function [dbo].[udf-Geo-Meters](@Lat1 FLOAT, @Lng1 FLOAT, @Lat2 FLOAT, @Lng2 FLOAT)
Returns Float as
Begin
Return ACOS(SIN(PI()*@Lat1/180.0)*SIN(PI()*@Lat2/180.0)+COS(PI()*@Lat1/180.0)*COS(PI()*@Lat2/180.0)*COS(PI()*@Lng2/180.0-PI()*@Lng1/180.0)) * 6371008.8
-- 6.371 mean radius of earth in meters
End
我应该补充一点,UDF计算实际上是谷歌地图计算的现场点。
答案 1 :(得分:3)
为了略微改善约翰的回答,这就是你能做的:
CREATE TABLE YourTable (
ID INT PRIMARY KEY
, Lat FLOAT
, Lon FLOAT
, Location AS GEOGRAPHY::Point(Lat, Lon, 4326));
INSERT INTO YourTable (ID, Lat, Lon)
VALUES
(1,-8.157908, -34.931675)
, (2,-8.164891, -34.919033)
, (3,-8.159999, -34.939999);
GO
CREATE FUNCTION GetCloserThanOneKilometer (
@Lat FLOAT
, @Lon FLOAT
, @Distance FLOAT)
RETURNS TABLE
AS
RETURN
SELECT *
FROM YourTable
WHERE GEOGRAPHY::Point(@Lat, @Lon, 4326).STDistance(Location) <= @Distance;
您将拥有一个存储坐标的计算列。因此,为了抽象和简化查询,您可以创建一个内联函数,我巧妙地将其命名为GetCloserThanOneKilometer
,然后按如下方式运行查询,以根据您的给定纬度和经度以及距离(必须低于您的输入)获取数据( @Distance
param):
SELECT *
FROM GetCloserThanOneKilometer(-8.157908, -34.931675, 1000);
GO