地理空间数据库作业笔记——查询最偏僻的城市

3.6.8 查询哪个城市最偏僻,即离高速公路的距离最远,通过display函数在地图上展示最偏僻的城市和与其最近的高速公路,display函数要求查询结果模式至少包含gid,name和geom属性,其中高速公路的name为full_name(4分)

解题思路:

  1. 定义"偏僻":城市到最近高速公路的距离最远

  2. 两步查询

    • 第一步:找到距离高速公路最远的城市

    • 第二步:找到离这个城市最近的高速公路(用于地图展示)

代码详解:

sql

复制代码
# 查询最偏僻的城市
query1 = """
WITH city_highway_distances AS (
    SELECT 
        c.gid,
        c.name,
        c.geom,
        MIN(ST_Distance(c.geom::geography, h.geom::geography)) as min_distance
    FROM uscities c, ushighways h
    WHERE c.geom IS NOT NULL AND h.geom IS NOT NULL
    GROUP BY c.gid, c.name, c.geom
)
SELECT 
    gid, 
    name, 
    geom,
    min_distance
FROM city_highway_distances
ORDER BY min_distance DESC
LIMIT 1
"""

关键点解释:

  • **WITH city_highway_distances AS (...):**创建公共表表达式,计算每个城市到所有高速公路的最小距离

  • **ST_Distance(c.geom::geography, h.geom::geography):**将geometry转换为geography类型,计算真实地球距离(米)

  • **MIN(...):**对每个城市,找到到所有高速公路中的最小距离

  • GROUP BY c.gid, c.name, c.geom:按城市分组,计算每个城市的最小距离

  • ORDER BY min_distance DESC LIMIT 1:按距离降序排列,取最远的城市

sql

复制代码
# 查询与最偏僻的城市最近的高速公路
query2 = """ 
WITH farthest_city AS (
    WITH city_highway_distances AS (
        SELECT 
            c.gid as city_gid,
            c.name as city_name,
            c.geom as city_geom,
            h.gid as highway_gid,
            h.full_name as highway_name,
            h.geom as highway_geom,
            ST_Distance(c.geom::geography, h.geom::geography) as distance
        FROM uscities c, ushighways h
        WHERE c.geom IS NOT NULL AND h.geom IS NOT NULL
    ),
    min_distances AS (
        SELECT 
            city_gid,
            MIN(distance) as min_distance
        FROM city_highway_distances
        GROUP BY city_gid
    )
    SELECT 
        chd.city_gid,
        chd.city_name,
        chd.city_geom,
        chd.highway_gid,
        chd.highway_name,
        chd.highway_geom,
        chd.distance
    FROM city_highway_distances chd
    JOIN min_distances md ON chd.city_gid = md.city_gid AND chd.distance = md.min_distance
    ORDER BY chd.distance DESC
    LIMIT 1
)
SELECT 
    highway_gid as gid,
    highway_name as name,
    highway_geom as geom
FROM farthest_city
"""

嵌套WITH子句说明:

  • 最内层:计算每个城市到每条高速公路的距离

  • 中间层:找到每个城市的最小距离

  • 最外层:通过JOIN找到对应最小距离的具体高速公路信息

* GROUP BY 详解

基本概念

GROUP BY 是 SQL 中用于对查询结果进行分组的关键字, 它通常与聚合函数(如 COUNT, SUM, AVG, MAX, MIN 等)一起使用。GROUP BY 语句将查询结果按照一个或多个列的值进行分组,然后对每个组应用聚合函数计算统计值。

基本语法

sql 复制代码
SELECT column_name(s), aggregate_function(column_name)
FROM table_name
WHERE condition
GROUP BY column_name(s)
[ORDER BY column_name(s)];

详细说明

1. 单列分组

最常见的用法是只按一个列进行分组:

sql 复制代码
SELECT department, COUNT(*) as employee_count
FROM employees
GROUP BY department;

这个查询会统计每个部门的员工数量。

2. 多列分组

可以同时按多个列进行分组:

sql 复制代码
SELECT department, job_title, AVG(salary) as avg_salary
FROM employees
GROUP BY department, job_title;

这个查询会计算每个部门中每个职位的平均薪资。

3. 与聚合函数配合使用

GROUP BY 通常与以下聚合函数配合使用:

  • COUNT(): 计算行数
  • SUM(): 计算总和
  • AVG(): 计算平均值
  • MAX(): 获取最大值
  • MIN(): 获取最小值
4. HAVING 子句

HAVING 子句用于过滤分组后的结果:

sql 复制代码
SELECT department, COUNT(*) as employee_count
FROM employees
GROUP BY department
HAVING COUNT(*) > 5;

这个查询只返回员工数超过5人的部门。

5. 执行顺序

在 SQL 查询中,GROUP BY 的执行顺序如下:

  1. FROM 子句
  2. WHERE 子句
  3. GROUP BY 子句
  4. HAVING 子句
  5. SELECT 子句
  6. ORDER BY 子句

实际应用场景

1. 销售数据分析
sql 复制代码
SELECT product_category, 
       SUM(sales_amount) as total_sales,
       AVG(sales_amount) as avg_sales,
       COUNT(*) as transaction_count
FROM sales
WHERE sale_date BETWEEN '2023-01-01' AND '2023-12-31'
GROUP BY product_category
HAVING SUM(sales_amount) > 10000
ORDER BY total_sales DESC;
2. 用户行为分析
sql 复制代码
SELECT user_segment, 
       COUNT(DISTINCT user_id) as unique_users,
       AVG(session_duration) as avg_duration,
       SUM(page_views) as total_views
FROM user_sessions
GROUP BY user_segment;
3. 库存管理
sql 复制代码
SELECT warehouse_location, 
       product_type,
       SUM(current_stock) as total_inventory,
       MIN(last_restock_date) as oldest_stock
FROM inventory
GROUP BY warehouse_location, product_type;

注意事项

  1. SELECT 子句中出现的非聚合列必须包含在 GROUP BY 子句中
  2. WHERE 子句在分组前过滤行,而 HAVING 子句在分组后过滤组
  3. GROUP BY 的性能可能会受到数据量的影响,在大表上使用时要考虑索引优化
  4. 某些数据库支持 GROUPING SETS、CUBE 和 ROLLUP 等高级分组操作

* ORDER BY 基本语法

ORDER BY 子句用于对查询结果进行排序,可以按一个或多个列排序,支持升序(ASC)或降序(DESC)。默认排序方式为升序。

sql 复制代码
SELECT column1, column2, ...
FROM table_name
ORDER BY column1 [ASC|DESC], column2 [ASC|DESC], ...;

单列排序

按单个列排序,例如按 salary 降序排列:

sql 复制代码
SELECT name, salary
FROM employees
ORDER BY salary DESC;

多列排序

可以同时按多个列排序,例如先按 department 升序,再按 salary 降序:

sql 复制代码
SELECT name, department, salary
FROM employees
ORDER BY department ASC, salary DESC;

按表达式或函数排序

可以使用表达式或函数进行排序,例如按 name 长度排序:

sql 复制代码
SELECT name, LENGTH(name) AS name_length
FROM employees
ORDER BY name_length;

按列别名排序

如果查询结果中包含别名列,可以直接使用别名排序:

sql 复制代码
SELECT name, salary * 12 AS annual_salary
FROM employees
ORDER BY annual_salary DESC;

按列位置排序

可以按 SELECT 语句中的列序号排序(从 1 开始),例如按第 2 列(salary)排序:

sql 复制代码
SELECT name, salary
FROM employees
ORDER BY 2 DESC;

NULL 值的处理

NULL 值在排序时默认被视为最小值(升序时排在最前,降序时排在最后)。可以使用 NULLS FIRSTNULLS LAST 调整 NULL 值的位置:

sql 复制代码
SELECT name, commission
FROM employees
ORDER BY commission DESC NULLS LAST;

与 LIMIT 结合使用

ORDER BY 常与 LIMIT 配合使用,例如查询薪资最高的 5 名员工:

sql 复制代码
SELECT name, salary
FROM employees
ORDER BY salary DESC
LIMIT 5;

在 JOIN 查询中使用

在多表 JOIN 查询时,ORDER BY 可以按任意表的列排序:

sql 复制代码
SELECT e.name, d.department_name, e.salary
FROM employees e
JOIN departments d ON e.department_id = d.id
ORDER BY d.department_name, e.salary DESC;

3.6.9 查询哪些高速公路穿越湖,列出高速公路及其在湖中的长度,按长度从长到短排列,通过display函数在地图上展示这些高速公路和湖,display函数要求查询结果模式至少包含gid,name和geom属性, 其中高速公路的hname为full_name(4分)

3.6.10 将交通事故与高速公路基于空间距离进行关联,即距离某高速公路小于200米,认为该交通事故发生在这条高速公路上,查询哪条高速公路上的交通事故最多?由于交通事故较多,完整的查询大约需要30分钟,可以使用ST_DWithin加速距离判断,同时仅考虑在10月发生的交通事故。通过display函数在地图上展示这些高速公路和其关联的交通事故,display函数要求查询结果模式至少包含gid,name和geom属性,其中高速公路的name为full_name。本题在台式机上查询时间约为3分钟(5分)
空间关联查询 :此类空间关联查询是数据挖掘中的常见方法,应用较为广泛,如道路与车辆关联分析道路拥堵情况?

3.6.11 导入加州cal的shapefile文件,修改空间参考系为4326,计算加州的经纬度范围,在该范围内,基于所给的网格生成代码,构建,即X方向50,Y方向46,网格与加州多边形求交,即边界上的方格仅保留与加州相交的部分,统计每个方格内的交通事故数目,通过choroplethMap进行可视化,choroplethMap函数要求查询结果模式至少包含gid,name,geom和value属性,其中name和value均为其内的交通事故数目,可以通过with语句简化SQL语句(4分)
空间网格关联查询 :此类空间网格关联查询在实际应用中较为常见,如滴滴和Uber基于六边形网格统计打车人数,进行实时调价,Uber Deck Hexagon layer (中文Deck.gl)

3.6.12 查询在加州范围内的交通事故,通过heatMap进行可视化,heatMap函数要求查询结果模式至少包含gid,name和geom属性,其中name可为任意值(2分)
数据可视化 :利用人眼的感知能力对数据进行交互的可视表达以增强认知的技术,是数据分析的有效手段,如Uber数据可视化

  • ST_NPoints(): 计算几何对象中的点数

  • ST_ConvexHull(): 计算几何对象的凸包

  • ST_NumInteriorRings(): 计算多边形中的内环数(岛的数量)

  • ST_Area(): 计算几何对象的面积

  • ST_Length(): 计算几何对象的长度

  • ST_Centroid(): 计算几何对象的质心

  • ST_Distance(): 计算两个几何对象之间的距离

  • ST_Touches(): 判断两个几何对象是否接触

相关推荐
yi碗汤园3 小时前
【一文了解】八大排序-插入排序、希尔排序
开发语言·算法·unity·c#·1024程序员节
Icoolkj3 小时前
Edge-TTS+Cloudflare Worker:免费 TTS 服务搭建指南,支持 API 调用与低代码集成
1024程序员节
小莞尔3 小时前
【51单片机】【protues仿真】基于51单片机智能温控风扇系统
c语言·单片机·嵌入式硬件·物联网·51单片机·1024程序员节
呆呆小金人3 小时前
Linux:开源时代的隐形基石
linux·1024程序员节
没有bug.的程序员3 小时前
Spring 常见问题与调试技巧
java·后端·spring·动态代理·1024程序员节
Han.miracle3 小时前
数据结构——排序的超级详解(Java版)
java·数据结构·学习·算法·leetcode·排序算法·1024程序员节
hazy1k3 小时前
51单片机基础-DS18B20温度传感器
c语言·stm32·单片机·嵌入式硬件·51单片机·1024程序员节
AI棒棒牛3 小时前
论文精读系列:Retinanet——目标检测领域中的SCI对比实验算法介绍!可一键跑通的对比实验,极大节省小伙伴的时间!!!
yolo·目标检测·计算机视觉·对比实验·1024程序员节·创新·rtdter