【问题标题】:SQL - Most frequent value in column of joined tablesSQL - 连接表列中最常见的值
【发布时间】:2017-03-28 14:24:01
【问题描述】:

我有如下描述的三个表:

Area (Id, Description)

City(Id, Name)

Problem(Id, City, Area, Definition):
 City references City (Id), Area references Area (Id)

我想为每个城市(名称)找出问题中出现频率最高的区域(描述)值。

例子:

Area
Id   Description
1      Support
2      Finance  

City
Id      Name
1      Chicago
2      Boston

Problem
Id  City  Area  Definition
1     1     2       A
2     1     2       B
3     1     1       C
4     2     1       D

期望的输出:

 Name         Description
 Chicago        Finance
 Boston         Support

这是我尝试过但没有成功的方法:

SELECT Name,
       Description
FROM
  (SELECT *
   FROM Problem AS P,
        City AS C,
        Area AS A
   WHERE C.Id = P.City
     AND A.Id = P.Area ) AS T1
WHERE Description =
    (SELECT Description
     FROM
       (SELECT *
        FROM Problem AS P,
             City AS C,
             Area AS A
        WHERE C.Id = P.City
          AND A.Id = P.Area ) AS T2
     WHERE T1.Name = T2.Name
     GROUP BY Description
     ORDER BY Count(Name) DESC LIMIT 1 )
GROUP BY Name,
         Description

谢谢!

【问题讨论】:

  • 请发布一些示例输入和所需的输出...
  • 没有任何时间戳字段的最近区域的标准是什么?
  • 这实际上是每个城市的问题中出现频率最高的区域值。和这个问题类似:stackoverflow.com/questions/12235595/… 但是使用了三个表
  • 听起来像是每组前 N 个问题。已经有大量的解决方案。
  • 我想在这里看到一些模拟数据和预期结果。我看到它的方式你想在结果中看到 city.name 和 area.description 但我不确定还有什么。 “最常见的面积值”这句话对我来说毫无意义。如果将城市和区域作为内部连接加入问题并计算 id,我们将获得每个区域和城市的计数。但由于它是聚合的,因此没有“最频繁”。

标签: mysql sql


【解决方案1】:

每个城市的最大,面积应该是

  select  C.Name, A.Description from (
    select t1.City, t1.Area, max(freq)  as max_freq
    from (
        select P.City, P.Area, count(*) as Freq
        from Problem as P 
        group by P.City, P.Area
    ) t1
  ) t2 
  INNER JOIN City AS C ON t2.City = C.Id
  INNER JOIN Area AS A ON A.Id = t2.Area

【讨论】:

  • 这里的技巧是针对每个城市的,所以需要返回超过 1 条记录
  • @xQbert 。谢谢..我已经为每个城市更新了一个新的答案(希望)
  • 我写了同样的查询,但没有发布(虽然我在最里面的查询中连接了城市和区域).. 因为你只显示名称和描述你为什么需要任何内联视图?我们按城市汇总的一个,最大面积并没有给我们带来任何新的东西。这里的问题是问题本身没有足够的意义。 (为什么我们不能通过 c.name 和 a.description 将问题加入到 city 和 area 和 group 或做一个不同的。我们会得到相同的结果而没有所有子查询。所以我们错过了一些东西。
  • @xQbert 。使用这么多内联视图..是因为..我累的时候一步一步思考..当我有点累和困的时候我不能一次抽象整个查询..使用max..是因为(我不知道真实数据)查询可以为城市返回更多不同的 ro,具有不同计数()的区域,因此 max 仅使用一个(最大值)过滤这一行......并且最后一个没有适当的集合数据和预期结果..如果我们遗漏了什么或者我们是对的,这是不可能的..
  • 我的意思是这在逻辑上似乎是正确的;但它可以通过以下方式轻松实现:SELECT Distinct C.name, A.Description FROM Problem INNER JOIN City C on C.ID = maxFreq.City INNER JOIN Area A on A.ID = MaxFreq.Area 但这似乎错过了作者之后的内容,直到他们为问题提供更好的背景,我们才能知道。
【解决方案2】:

这可能是解决您的问题的最短方法:

select c.Name, a.Description
from City c
cross join Area a
where a.Id = (
    select p.Area
    from Problem p
    where p.City = c.Id
    group by p.Area
    order by count(*) desc, p.Area asc
    limit 1
)

我们使用 CROSS JOIN 将每个 City 与每个 Area 组合起来。但是我们只选择Problem 表中给定城市的计数最高的Area,这是在相关子查询中确定的。如果两个地区的城市数量相同,则会选择按字母顺序排在第一位的地区 (order by ... p.Area asc)。

结果:

|    Name | Description |
|---------|-------------|
|  Boston |     Support |
| Chicago |     Finance |

这是另一个更复杂的解决方案,其中包括计数。

select c.Name, a.Description, city_area_maxcount.mc as problem_count
from (
    select City, max(c) as mc
    from (
        select p.City, p.Area, count(*) as c
        from problem p
        group by p.City, p.Area
    ) city_area_count
    group by City
) city_area_maxcount
join (
    select p.City, p.Area, count(*) as c
    from problem p
    group by p.City, p.Area
) city_area_count
    on  city_area_count.City = city_area_maxcount.City
    and city_area_count.c = city_area_maxcount.mc
join City c on c.Id = city_area_count.City
join Area a on a.Id = city_area_count.Area

子查询别名city_area_maxcount在这里被使用了两次(我希望mysql可以缓存结果)。如果您将其视为一张表格,那将是一个常见的 find-the-row-with-top-value-per-group 问题。如果两个区域对一个城市的最高计数相同,则两者都将被选中。

结果:

|    Name | Description | problem_count |
|---------|-------------|---------------|
|  Boston |     Support |             1 |
| Chicago |     Finance |             2 |

演示:http://sqlfiddle.com/#!9/c66a5/2

【讨论】:

    猜你喜欢
    • 2015-06-21
    • 1970-01-01
    • 2012-08-27
    • 2021-07-13
    • 2021-11-07
    • 2018-06-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多