【问题标题】:Write SQL query that finds the most common first name(S), errors编写查找最常见名字(S)、错误的 SQL 查询
【发布时间】:2020-02-11 21:08:01
【问题描述】:

给定一个名为 USERS_FAKE U 的表,我需要编写一个查询来查找最常见的名字。

我的问题是我只设法编写了一个只返回一个常见名字的查询。但是,如果名称“Bob”出现 6 次,使其成为最常见的名字,并且还有其他名称出现 6 次(如“Mike”),我的查询将只返回“Bob”。我的查询应该返回 Bob 和 Mike,因为它们的出现次数相同。

尝试 MCRE:

-- The table we are working with
CREATE TABLE USERS_FAKE (
    USER_ID NUMBER PRIMARY KEY,
    FIRST_NAME VARCHAR2(100) NOT NULL,
    LAST_NAME VARCHAR2(100) NOT NULL
);

-- Test Data, to test that we return the Most Common First Name(s)
-- (clearly there are 2 Most Common First Name(s): Bob and Mike)
INSERT INTO USERS_FAKE VALUES(5,  'Bob',  'Io');
INSERT INTO USERS_FAKE VALUES(6,  'Bob',  'Io');
INSERT INTO USERS_FAKE VALUES(7,  'Bob',  'Io');
INSERT INTO USERS_FAKE VALUES(8,  'Bob',  'Io');
INSERT INTO USERS_FAKE VALUES(9,  'Bob',  'Io');
INSERT INTO USERS_FAKE VALUES(10, 'Bob',  'Io');
INSERT INTO USERS_FAKE VALUES(11, 'Mike',  'Ganymede');
INSERT INTO USERS_FAKE VALUES(12, 'Mike',  'Ganymede');
INSERT INTO USERS_FAKE VALUES(13, 'Mike',  'Ganymede');
INSERT INTO USERS_FAKE VALUES(14, 'Mike',  'Ganymede');
INSERT INTO USERS_FAKE VALUES(15, 'Mike',  'Ganymede');
INSERT INTO USERS_FAKE VALUES(16, 'Mike',  'Ganymede');

我需要编写一个使用聚合 + WHERE 子句的简单查询,但您在 SQL 中将两者结合起来。这是在 Oracle 中,我必须使用 ROWNUMLIMIT 在我的环境中不起作用。

【问题讨论】:

标签: sql oracle


【解决方案1】:

WHERE 子句中不允许聚合。您希望查询返回与最常见名称的出现次数相关联的名称。相反,应该使用HAVING 子句,因为HAVING 子句用于在SQL 中聚合之后过滤组。

见下例:

SELECT DISTINCT FIRST_NAME, COUNT(FIRST_NAME) AS MOST_FREQUENT 
FROM USERS_FAKE
GROUP BY FIRST_NAME
HAVING COUNT(FIRST_NAME) = (SELECT COUNT(FIRST_NAME) AS NUM_FREQUENCY 
                            FROM USERS_FAKE
                            GROUP BY FIRST_NAME
                            ORDER BY NUM_FREQUENCY DESC
                            LIMIT 1)
;

另外我个人推荐row_number()

SELECT T.FIRST_NAME
FROM (
       SELECT N.FIRST_NAME AS FIRST_NAME
            , ROW_NUMBER() OVER (ORDER BY N.NUM_FREQUENCY DESC) AS ROW_NUM
       FROM (
               SELECT FIRST_NAME
                    , COUNT(FIRST_NAME) AS NUM_FREQUENCY 
               FROM USERS_FAKE
               GROUP BY FIRST_NAME
               ORDER BY NUM_FREQUENCY
            ) AS N
      ) AS T
WHERE T.ROW_NUM = 1
;

ROW_NUMBER() 按出现次数对名称进行排名,然后查询返回与最常见名称相关的第一行。在这种情况下,ROW_NUMBER() 不是最佳解决方案。但是,这可能是实现“发生很重要”场景的一种简单方法。

【讨论】:

  • 谢谢,你的答案最接近我需要的答案。我将第一个代码的LIMIT 1 更改为FETCH FIRST ROW ONLY
【解决方案2】:
SELECT n.first
FROM names n
JOIN ( SELECT first, COUNT(*) AS cnt
       FROM names
       GROUP BY first
     ) n1 ON ( n1.first = n.first )
ORDER BY n1.cnt DESC group by n.first;

【讨论】:

    【解决方案3】:

    我会使用 RANK() 函数

    SELECT   t.first_name, t.count FROM
     (
       SELECT
       first_name, COUNT(1) AS count,
       RANK () OVER (  ORDER BY COUNT(1) DESC ) rank_no 
       FROM USERS_FAKE
       GROUP BY first_name
     ) AS t
     WHERE rank_no = 1
    

    【讨论】:

      猜你喜欢
      • 2014-08-04
      • 2013-03-02
      • 1970-01-01
      • 1970-01-01
      • 2021-04-20
      • 2012-08-27
      • 2011-09-16
      • 1970-01-01
      相关资源
      最近更新 更多