根据经纬度数据计算空间距离-Go语言实现

主要目的
计算每个出租车接客和送客地点与15个银行的距离,对于满足距离小于等于97m条件的银行和出租车接/送客信息实现匹配。

1、银行所在地点的经纬度

在这里插入图片描述

2、出租车接/送客地点的经纬度

在这里插入图片描述

3、距离计算并统计

package main

import (
	"encoding/csv"
	"fmt"
	"io"
	"log"
	"math"
	"os"
	"strconv"
)

func Distance_list(fileName string) {
	// 定义一个字符串数组,保存接客计算结果
	result_index1 := []string{}
	result_name1 := []string{}
	// 定义一个字符串数组,保存送客计算结果
	result_index2 := []string{}
	result_name2 := []string{}
	// fmt.Println(result)
	data_bank_name := [15]string{"Bank of America(investment banking)", "Barclays(Investment Bank)", "BNY Mellon (headquarters)", "Citigroup(global markets)", "Credit Suisse", "Deutsche Bank", "Deutsche Bank(securities)", "Goldman Sachs(headquarters)", "JPMorgan Chase (investment banking)", "JPMorgan Chase(headquarters)", "Morgan Stanley(headquarters)", "Morgan Stanley(investment management)", "RBC Capital Markets ", "UBS(USA)Inc(Private wealth management)", "BNY Mellon (headquarters) (2014/6)"}
	// 经度
	data_bank_lon := [15]float64{-73.984167, -73.9853352, -74.0126052, -74.011036, -73.986556, -73.9725, -74.0105799, -74.014444, -73.977089, -73.9754, -73.985678, -73.980556, -74.0169804, -73.9763302, -74.015556}
	// 纬度
	data_bank_lat := [15]float64{40.755278, 40.76052, 40.7069034, 40.720685, 40.741556, 40.7578, 40.7062295, 40.714722, 40.755585, 40.7558, 40.760386, 40.754722, 40.7139824, 40.756043, 40.713056}
	//将经纬度数据保存为数组
	pick_lon := []float64{}
	pick_lat := []float64{}
	drop_lon := []float64{}
	drop_lat := []float64{}
	//准备读取文件
	fs, err := os.Open(fileName)
	if err != nil {
		log.Fatalf("can not open the file, err is %+v", err)
	}
	defer fs.Close()
	r := csv.NewReader(fs)
	//针对大文件,一行一行的读取文件
	for {
		row, err := r.Read()
		if err != nil && err != io.EOF {
			log.Fatalf("can not read, err is %+v", err)
		}
		if err == io.EOF {
			break
		}
		lon1, _ := strconv.ParseFloat(row[0], 64)
		pick_lon = append(pick_lon, lon1)
		// fmt.Println(lat1)
		lat1, _ := strconv.ParseFloat(row[1], 64)
		pick_lat = append(pick_lat, lat1)

		lon2, _ := strconv.ParseFloat(row[2], 64)
		drop_lon = append(drop_lon, lon2)
		// fmt.Println(lat1)
		lat2, _ := strconv.ParseFloat(row[3], 64)
		drop_lat = append(drop_lat, lat2)
	}
	// 遍历循环计算距离-接客
	var i, j int
	// 计算距离
	for i = 0; i < len(pick_lon); i++ {
		for j = 0; j < 15; j++ {
			//转化为弧度(rad)
			const EARTH_RADIUS = 6378137  // 6378137(地球赤道半径:m)
			rad := math.Pi / 180.0
			// 1 、先获取银行的经纬度
			lon := float64(data_bank_lon[j])*rad
			lat := float64(data_bank_lat[j])*rad
			if lon < 0 {
				lon = math.Pi*2 - math.Abs(lon)
			}
			if lat > 0 {
				lat = math.Pi/2 - math.Abs(lat)
			}
			// 2、获取接客经纬度
			lon1 := pick_lon[i] * rad
			lat1 := pick_lat[i] * rad
			if lon1 < 0 {
				lon1 = math.Pi*2 - math.Abs(lon1)
			}
			if lat1 > 0 {
				lat1 = math.Pi/2 - math.Abs(lat1)
			}
			// 3、获取送客经纬度
			lon2 := drop_lon[i] * rad
			lat2 := drop_lat[i] * rad
			if lon2 < 0 {
				lon2 = math.Pi*2 - math.Abs(lon2)
			}
			if lat2 > 0 {
				lat2 = math.Pi/2 - math.Abs(lat2)
			}
			// 4、换算
			x := EARTH_RADIUS * math.Cos(lon) * math.Sin(lat)
			y := EARTH_RADIUS * math.Sin(lon) * math.Sin(lat)
			z := EARTH_RADIUS * math.Cos(lat)
			x1 := EARTH_RADIUS * math.Cos(lon1) * math.Sin(lat1)
			y1 := EARTH_RADIUS * math.Sin(lon1) * math.Sin(lat1)
			z1 := EARTH_RADIUS * math.Cos(lat1)
			x2 := EARTH_RADIUS * math.Cos(lon2) * math.Sin(lat2)
			y2 := EARTH_RADIUS * math.Sin(lon2) * math.Sin(lat2)
			z2 := EARTH_RADIUS * math.Cos(lat2)
			// 5、求距离
			// 接客距离
			d1 := math.Sqrt((x1-x)*(x1-x) + (y1-y)*(y1-y) + (z1-z)*(z1-z))
			theta1 := math.Acos((EARTH_RADIUS*EARTH_RADIUS + EARTH_RADIUS*EARTH_RADIUS - d1*d1) / (2 * EARTH_RADIUS * EARTH_RADIUS))
			distance1 := theta1 * EARTH_RADIUS
			if distance1 <= 96.56064 {
				result_index1 = append(result_index1, strconv.Itoa(i))
				result_name1 = append(result_name1, data_bank_name[j])
			}
			// 送客距离
			d2 := math.Sqrt((x2-x)*(x2-x) + (y2-y)*(y2-y) + (z2-z)*(z2-z))
			theta2 := math.Acos((EARTH_RADIUS*EARTH_RADIUS + EARTH_RADIUS*EARTH_RADIUS - d2*d2) / (2 * EARTH_RADIUS * EARTH_RADIUS))
			distance2 := theta2 * EARTH_RADIUS
			if distance2 <= 96.56064 {
				result_index2 = append(result_index2, strconv.Itoa(i))
				result_name2 = append(result_name2, data_bank_name[j])
			}
		}
	}
	// 1、将接客信息存入文件
	path1 := "C:\\Users\\JunLiu\\Desktop\\数据分析\\香港中文大学商学院\\3-taxi\\pickup bank\\2016-06.csv"  //待更新
	//os.O_WRONLY | os.O_CREATE
	file1, err := os.OpenFile(path1, os.O_RDWR|os.O_APPEND|os.O_CREATE, 0666)
	if err != nil {
		fmt.Println("file open error:", err)
		return
	}
	defer file1.Close()
	//使用缓存方式写入
	writer1 := csv.NewWriter(file1)
	//写入表头
	head1 := []string{"index", "name"}  
	writer1.Write(head1)
	writer1.Flush()
	for i=0; i < len(result_index1); i++ {
		var d1 = []string{result_index1[i], result_name1[i]}
		writer1.Write(d1)
	}
	//将缓存中数据刷新到文本中
	writer1.Flush()
	fmt.Println("writedown_1 !!!")

	// 2、将送客信息存入文件
	path2 := "C:\\Users\\JunLiu\\Desktop\\数据分析\\香港中文大学商学院\\3-taxi\\dropoff bank\\2016-06.csv"  //待更新
	//os.O_WRONLY | os.O_CREATE
	file2, err := os.OpenFile(path2, os.O_RDWR|os.O_APPEND|os.O_CREATE, 0666)
	if err != nil {
		fmt.Println("file open error:", err)
		return
	}
	defer file2.Close()
	//使用缓存方式写入
	writer2 := csv.NewWriter(file2)
	//写入表头
	head2 := []string{"index", "name"}  
	writer2.Write(head2)
	writer2.Flush()
	for i=0; i < len(result_index2); i++ {
		var d2 = []string{result_index2[i], result_name2[i]}
		writer2.Write(d2)
	}
	//将缓存中数据刷新到文本中
	writer2.Flush()
	fmt.Println("writedown_2 !!!")
}

func main() {
	// 读取文件
	filePath := "C:\\Users\\JunLiu\\Desktop\\数据分析\\香港中文大学商学院\\3-taxi\\taxi_latlon\\2016-06.csv"    //待处理
	// runtime.GOMAXPROCS(4)         // 核心数 8
	fmt.Printf("start!\n")
	Distance_list(filePath)
	fmt.Printf("finish!")
}
<think>嗯,用户想了解SQL Server语句。首先,我需要回忆一下SQL Server中CREATE TABLE的基本语法结构。基础部分包括名、列名、数据类型,还有约束,比如主键、外键、非空这些。可能还要提到自字段,比如IDENTITY(1,1)这种。 用户可能刚开始学数据库,所以需要从简单例子入手。比如创一个学生,包含学号、姓名、年龄等字段。这候要明确每个列的数据类型,比如INT、VARCHAR,还有主键的设置方式,用PRIMARY KEY关键字。 另外,用户可能想知道更复杂的约束,比如默认值、唯一约束、检查约束。例如,给性别字段设置默认值,或者年龄必须大于0。这些约束在创候可以加上,或者在后面用ALTER TABLE添加。 还要考虑外键的情况,比如学生里可能有班级ID,关联到班级。这候需要用到FOREIGN KEY REFERENCES语句,确保引用的存在。 用户可能对自主键比较感兴趣,特别是在插入数据自动生成唯一值。这候要解释IDENTITY属性的用法,比如IDENTITY(1,1)示从1开始每次加1。 另外,需要注意SQL Server的数据类型,比如NVARCHAR和VARCHAR的区别,NVARCHAR支持Unicode,而VARCHAR是非Unicode的。还有日期类型用DATETIME还是DATE,根据需求选择。 可能会忘记提到的存储位置或者文件组,但对于初学者来说,可能暂不需要这些高级选项。不过如果用户问起,可以简要说明。 还要提醒用户注意语法正确,比如逗号的位置,括号的闭合,语句末尾的分号是否必要。SQL Server通常不强制分号,但在某些情况下可能需要,比如多个语句一起执行。 总结一下,回答的结构应该是先介绍基本语法,然后给出简单例子,再逐步添加约束和复杂结构,最后给出一个综合示例。这样用户能逐步理解,并且有参考的模板。同,要指出常见错误和注意事项,帮助用户避免问题。</think>SQL Server语句的核心语法及步骤如下: 一、基本语法结构 $$CREATE TABLE 名 ( 列名1 数据类型 [约束], 列名2 数据类型 [约束], ... [级约束] );$$ 二、核心组成部分解析 1. 列定义 - 必须包含列名和数据类型 - 常用数据类型: * 整数:`INT`, `SMALLINT`, `BIGINT` * 小数:`DECIMAL(p,s)`, `FLOAT` * 字符:`VARCHAR(n)`, `CHAR(n)`, `NVARCHAR(n)`(Unicode) * 日期:`DATETIME`, `DATE`, `TIME` * 二进制:`VARBINARY(MAX)` 2. 常用列约束 - `PRIMARY KEY`:主键约束 - `IDENTITY(seed, increment)`:自列 - `NOT NULL`:非空约束 - `UNIQUE`:唯一约束 - `DEFAULT 默认值`:默认值约束 - `CHECK (条件)`:检查约束 - `FOREIGN KEY REFERENCES 主(主键列)`:外键约束 三、完整示例 ```sql CREATE TABLE Students ( StudentID INT PRIMARY KEY IDENTITY(1,1), Name NVARCHAR(50) NOT NULL, Gender CHAR(1) CHECK (Gender IN ('M', 'F')) DEFAULT 'M', BirthDate DATE, ClassID INT FOREIGN KEY REFERENCES Classes(ClassID), CreateTime DATETIME DEFAULT GETDATE() ); ``` 四、高级用法 1. 创指定文件组 $$CREATE TABLE ArchiveData ( ID INT PRIMARY KEY, Content VARCHAR(MAX) ) ON [SecondaryFileGroup];$$ 2. 创 ```sql -- 本地临(#开头) CREATE TABLE #TempTable ( ID INT, Value VARCHAR(20) ); -- 全局临(##开头) CREATE TABLE ##GlobalTemp ( SessionID UNIQUEIDENTIFIER ); ``` 五、最佳实践议 1. 命名规范 - 名使用帕斯卡命名法(如`OrderDetails`) - 列名使用驼峰命名法(如`unitPrice`) - 避免使用保留关键字 2. 设计注意事项 - 主键应选择最稳定的业务字段 - 合理设置`VARCHAR`长度,避免过大浪费存储 - 日期字段议使用`DATE`替代`VARCHAR` - 大文本使用`VARCHAR(MAX)`,二进制数据使用`VARBINARY(MAX)` 3. 修改结构(使用`ALTER TABLE`) ```sql -- 添加新列 ALTER TABLE Students ADD Email NVARCHAR(100); -- 修改列类型 ALTER TABLE Students ALTER COLUMN BirthDate DATETIME; -- 删除列 ALTER TABLE Students DROP COLUMN OldColumn; ``` 六、常见错误处理 1. 对象已存在错误:创前检查是否存在 ```sql IF NOT EXISTS (SELECT * FROM sys.tables WHERE name = 'Students') BEGIN CREATE TABLE Students (...) END ``` 2. 外键约束冲突:确保引用先被创 3. 数据类型不匹配:插入数据前验证格式 实际应用议结合SSMS的图形界面工具辅助生成基础脚本,再根据需求进行优化调整。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值