You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何编写SQL查询获取各地区频次最高的犯罪类型

我来帮你搞定这个需求!你的目标是找出每个地区里频次最高的犯罪类型,也就是把每个地区的犯罪类型按次数排序后,只保留排名第一的那条记录对吧?先给你分析下原SQL的问题:它确实能统计出每个地区所有犯罪类型的次数,但缺少了「筛选分组内最大值」的步骤。下面给你两种实用的解决方案:

解决方案:用窗口函数筛选分组内最高频次记录

我们可以借助窗口函数ROW_NUMBER()RANK())来给每个地区的犯罪类型按频次排序,再筛选出排名第一的结果。

方法一:用ROW_NUMBER()(每个地区仅返回一条结果)

如果某个地区有多种犯罪类型频次相同且都是最高,这个方法会随机选一条(具体取决于数据库的默认排序规则):

WITH CrimeCounts AS (
    SELECT 
        CrimeType.Category,
        District.Name AS DistrictName,
        COUNT(*) AS NoOfCrimes,
        -- 按地区分组,组内按犯罪次数降序排名
        ROW_NUMBER() OVER (PARTITION BY District.Name ORDER BY COUNT(*) DESC) AS Rank
    FROM Crime
    INNER JOIN CrimeType ON Crime.id_crime = CrimeType.id
    INNER JOIN District ON Crime.id_district = District.id
    GROUP BY CrimeType.Category, District.Name
)
SELECT Category, DistrictName, NoOfCrimes
FROM CrimeCounts
WHERE Rank = 1;

方法二:用RANK()(保留并列最高的结果)

如果需要保留某个地区里所有频次并列第一的犯罪类型,就用这个方法——它会让并列的记录排名都为1:

WITH CrimeCounts AS (
    SELECT 
        CrimeType.Category,
        District.Name AS DistrictName,
        COUNT(*) AS NoOfCrimes,
        -- 按地区分组,组内按犯罪次数降序排名,并列记录排名相同
        RANK() OVER (PARTITION BY District.Name ORDER BY COUNT(*) DESC) AS Rank
    FROM Crime
    INNER JOIN CrimeType ON Crime.id_crime = CrimeType.id
    INNER JOIN District ON Crime.id_district = District.id
    GROUP BY CrimeType.Category, District.Name
)
SELECT Category, DistrictName, NoOfCrimes
FROM CrimeCounts
WHERE Rank = 1;

方案原理说明

  1. 第一步通过CTECrimeCounts)完成你原SQL的分组统计,同时新增了Rank列:这个列会以地区为分组单位,在每个地区内部按犯罪次数从高到低给记录排名。
  2. 第二步只筛选Rank = 1的记录,就得到了每个地区频次最高的犯罪类型。

针对你给出的示例数据,执行后会得到你期望的结果:

Rape | Downtown | 10
Theft | Queens | 7

内容的提问来源于stack exchange,提问作者TheOpti

火山引擎 最新活动