【问题标题】:SQL find average number of tuples (neither max nor min)SQL 查找平均元组数(既不是最大值也不是最小值)
【发布时间】:2019-09-28 22:16:39
【问题描述】:

假设我有两个表PEOPLEWORK。我想找到所有work,既没有最大也没有最小数量的people

示例:

PEOPLE

ID NAME   WORK
1  Mark   Programmer
2  Sonia  Singer
3  Jack   Programmer
4  Mirco  Welder
5  Jeff   Welder
6  Tom    Welder

WORK

ID  WORK
1   Programmer
2   Singer
3   Welder

结果应该是:

Programmer

我怎样才能写出这样的MySQL query??

谢谢大家


您必须考虑到它是一种脑筋急转弯。比你肯定会找到一组 3 个元素:

1 Maximum represented by Welder job done by Mirco, Jeff and Tom
2 Medium represented by Programmer done by Mark and Jack who is the Job I would like to find
3 Minimum represented by Singer done only from Sonia

谢谢

【问题讨论】:

  • 别现在别人怎么样,但我看不懂问题
  • 什么风格的 SQL?

标签: sql database business-intelligence


【解决方案1】:

另一种方式。使用子查询查找最小和最大计数,并将其与每个工作的计数连接到另一个子查询。然后左连接并消除匹配最小或最大计数的行。

declare @people table (id int, name varchar(20), work varchar(50))
insert into @people
values (1,  'Mark'  , 'Programmer'),
(2,  'Sonia'  ,'Singer'),
(3,  'Jack',   'Programmer'),
(4,  'Mirco',  'Welder'),
(5,  'Jeff',   'Welder'),
(6,  'Tom',    'Welder')

select a.work
from ( -- A subquery that returns the count of each work
   select work, count(*) cnt
   from @people
   group by work
) a
left outer join ( -- a subquery that returns the min and max counts
   select min(cnt) mincount, max(cnt) maxcount
   from (
      select count(*) cnt
      from @people
      group by work
   ) b
) c
   on a.cnt = c.mincount
   or a.cnt = c.maxcount
where c.mincount is null

【讨论】:

  • 这与@Nick 的解决方案几乎相同,只是使用派生表而不是 CTE。
  • 这是唯一一种适用于MySql 版 HackerRank 测试页的解决方案!!。实际上该版本不支持limit 或其他declarationsfunction 在下面的解决方案中写道。谢谢大佬!!
【解决方案2】:

此查询适用于支持 CTE 的 SQL 风格(例如 SQL Server、PostgreSQL、MySQL 8+):

WITH counts AS
(SELECT WORK, COUNT(*) AS num
 FROM people
 GROUP BY WORK),
minmax AS 
(SELECT MIN(num) AS min, MAX(num) AS max
 FROM counts)
SELECT WORK
FROM counts c
JOIN minmax m ON c.num != m.min AND c.num != m.max

输出:

WORK
Programmer

Demo on dbfiddle

【讨论】:

    【解决方案3】:

    这是一种使用窗口函数的方法:

    • 首先使用聚合查询来计算每项工作的人数
    • 然后按人数升序和降序对作品进行排名
    • 最后,过滤掉顶部和底部的记录

    查询:

    SELECT work
    FROM (
        SELECT 
            work,
            ROW_NUMBER() OVER(ORDER BY cnt) rn_asc,
            ROW_NUMBER() OVER(ORDER BY cnt DESC) rn_desc
        FROM (
            SELECT work, COUNT(*) cnt FROM people GROUP BY work
        ) x
    ) x WHERE rn_asc != 1 AND rn_desc != 1
    

    Demo on DB Fiddle

    | work       |
    | ---------- |
    | Programmer |
    

    注意:就问题而言,您无需查询work 表即可获得预期结果,因为所有相关信息都在people 中提供。

    【讨论】:

      【解决方案4】:

      如果你想在没有窗口函数的情况下这样做:

      select w.*
      from work w
      where w.work not in (select p.work
                           from people p
                           group by p.work
                           order by count(*) asc
                           fetch first 1 row only
                          ) and
            w.work not in (select p.work
                           from people p
                           group by p.work
                           order by count(*) desc
                           fetch first 1 row only
                          );
      

      请注意,在出现重复的情况下,这只会考虑最小/最大的一行,因此可以返回平局。

      【讨论】:

        猜你喜欢
        • 2014-06-11
        • 2022-10-26
        • 2021-06-18
        • 1970-01-01
        • 2016-01-05
        • 2021-01-15
        • 2020-06-17
        • 2015-01-16
        • 1970-01-01
        相关资源
        最近更新 更多