当前位置: 首页 > 面试题库 >

MYSQL-按限制分组

凌嘉勋
2023-03-14
问题内容

有没有一种简单的方法可以将GROUP BY结果限制在前2位。以下查询返回所有结果。使用“ LIMIT 2”将整个列表减少到仅前2个条目。

select distinct(rating_name), 
       id_markets, 
       sum(rating_good) 'good', 
       sum(rating_neutral)'neutral', 
       sum(rating_bad) 'bad' 
 from ratings 
 where rating_year=year(curdate()) and rating_week= week(curdate(),1)
 group by rating_name,id_markets
 order by rating_name, sum(rating_good) 
 desc

结果如下:

波兰78 48 24 12 <-保持
波兰1 15 5 0 <-保持
波兰23 12 6 3
波兰2 5 0 0
波兰3 0 5 0
波兰4 0 0 5
爱尔兰1 9 3 0 <-保持
爱尔兰2 3 0 0 <-保持
爱尔兰3 0 3 0
爱尔兰4 0 0 3
法国12 24 12 6 <-保持
法国1 3 1 0 <-保持
法国231 1 0 0
法国2 1 0 0
法国4 0 0 1
法国3 0 1 0

谢谢乔恩

根据要求,我附上了表格结构和一些测试数据的副本。我的目标是创建一个视图,该视图具有每个唯一的rating_name的前2个结果

CREATE TABLE `zzratings` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `id_markets` int(11) DEFAULT NULL,
  `id_account` int(11) DEFAULT NULL,
  `id_users` int(11) DEFAULT NULL,
  `dateTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
  `rating_good` int(11) DEFAULT NULL,
  `rating_neutral` int(11) DEFAULT NULL,
  `rating_bad` int(11) DEFAULT NULL,
  `rating_name` varchar(32) DEFAULT NULL,
  `rating_year` smallint(4) DEFAULT NULL,
  `rating_week` tinyint(4) DEFAULT NULL,
  `cash_balance` decimal(9,6) DEFAULT NULL,
  `cash_spend` decimal(9,6) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `rating_year` (`rating_year`),
  KEY `rating_week` (`rating_week`),
  KEY `rating_name` (`rating_name`)
) ENGINE=MyISAM AUTO_INCREMENT=2166690 DEFAULT CHARSET=latin1;

INSERT INTO `zzratings` (`id`,`id_markets`,`id_account`,`id_users`,`dateTime`,`rating_good`,`rating_neutral`,`rating_bad`,`rating_name`,`rating_year`,`rating_week`,`cash_balance`,`cash_spend`)
VALUES
    (63741, 1, NULL, 100, NULL, 1, NULL, NULL, 'poland', 2010, 15, NULL, NULL),
    (63742, 1, NULL, 101, NULL, 1, NULL, NULL, 'poland', 2010, 15, NULL, NULL),
    (1, 2, NULL, 102, NULL, 1, NULL, NULL, 'poland', 2010, 15, NULL, NULL),
    (63743, 3, NULL, 103, NULL, NULL, 1, NULL, 'poland', 2010, 15, NULL, NULL),
    (63744, 4, NULL, 104, NULL, NULL, NULL, 1, 'poland', 2010, 15, NULL, NULL),
    (63745, 1, NULL, 105, NULL, 1, NULL, NULL, 'poland', 2010, 15, NULL, NULL),
    (63746, 1, NULL, 106, NULL, NULL, 1, NULL, 'poland', 2010, 15, NULL, NULL),
    (63747, 5, NULL, 100, NULL, 1, NULL, NULL, 'ireland', 2010, 15, NULL, NULL),
    (63748, 5, NULL, 101, NULL, 1, NULL, NULL, 'ireland', 2010, 15, NULL, NULL),
    (63749, 2, NULL, 102, NULL, 1, NULL, NULL, 'ireland', 2010, 15, NULL, NULL),
    (63750, 3, NULL, 103, NULL, NULL, 1, NULL, 'ireland', 2010, 15, NULL, NULL),
    (63751, 4, NULL, 104, NULL, NULL, NULL, 1, 'ireland', 2010, 15, NULL, NULL),
    (63752, 1, NULL, 105, NULL, 1, NULL, NULL, 'ireland', 2010, 15, NULL, NULL),
    (63753, 1, NULL, 106, NULL, NULL, 1, NULL, 'ireland', 2010, 15, NULL, NULL),
    (63754, 1, NULL, 100, NULL, 1, NULL, NULL, 'ireland', 2010, 15, NULL, NULL),
    (63755, 1, NULL, 101, NULL, 1, NULL, NULL, 'ireland', 2010, 15, NULL, NULL),
    (63756, 2, NULL, 102, NULL, 1, NULL, NULL, 'ireland', 2010, 15, NULL, NULL),
    (63757, 34, NULL, 103, NULL, NULL, 1, NULL, 'ireland', 2010, 15, NULL, NULL),
    (63758, 34, NULL, 104, NULL, NULL, NULL, 1, 'ireland', 2010, 15, NULL, NULL),
    (63759, 34, NULL, 105, NULL, 1, NULL, NULL, 'ireland', 2010, 15, NULL, NULL),
    (63760, 34, NULL, 106, NULL, NULL, 1, NULL, 'ireland', 2010, 15, NULL, NULL),
    (63761, 21, NULL, 100, NULL, 1, NULL, NULL, 'ireland', 2010, 15, NULL, NULL),
    (63762, 21, NULL, 101, NULL, 1, NULL, NULL, 'ireland', 2010, 15, NULL, NULL),
    (63763, 21, NULL, 102, NULL, 1, NULL, NULL, 'ireland', 2010, 15, NULL, NULL),
    (63764, 21, NULL, 103, NULL, NULL, 1, NULL, 'ireland', 2010, 15, NULL, NULL),
    (63765, 4, NULL, 104, NULL, NULL, NULL, 1, 'ireland', 2010, 15, NULL, NULL),
    (63766, 1, NULL, 105, NULL, 1, NULL, NULL, 'ireland', 2010, 15, NULL, NULL),
    (63767, 1, NULL, 106, NULL, NULL, 1, NULL, 'ireland', 2010, 15, NULL, NULL),
    (63768, 1, NULL, 100, NULL, 1, NULL, NULL, 'france', 2010, 15, NULL, NULL),
    (63769, 1, NULL, 101, NULL, 1, NULL, NULL, 'france', 2010, 15, NULL, NULL),
    (63770, 2, NULL, 102, NULL, 1, NULL, NULL, 'france', 2010, 15, NULL, NULL),
    (63771, 3, NULL, 103, NULL, NULL, 1, NULL, 'france', 2010, 15, NULL, NULL),
    (63772, 4, NULL, 104, NULL, NULL, NULL, 1, 'france', 2010, 15, NULL, NULL);

问题答案:

我认为MySQL中没有简单的方法。一种方法是通过为按rating_name分组的每一行生成一个行号,然后仅选择row_number为2或更少的行。在大多数数据库中,您可以使用以下方法进行此操作:

SELECT * FROM (
    SELECT
        rating_name,
        etc...,
        ROW_NUMBER() OVER (PARTITION BY rating_name ORDER BY good) AS rn
    FROM your_table
) T1
WHERE rn <= 2

不幸的是,MySQL不支持该ROW_NUMBER语法。但是,您可以ROW_NUMBER使用变量进行模拟:

SELECT
    rating_name, id_markets, good, neutral, bad
FROM (
    SELECT
        *,
        @rn := CASE WHEN @prev_rating_name = rating_name THEN @rn + 1 ELSE 1 END AS rn,
        @prev_rating_name := rating_name
    FROM (
        SELECT
            rating_name,
            id_markets,
            SUM(COALESCE(rating_good, 0)) AS good,
            SUM(COALESCE(rating_neutral, 0)) AS neutral,
            SUM(COALESCE(rating_bad, 0)) AS bad
        FROM zzratings
        WHERE rating_year = YEAR(CURDATE()) AND rating_week = WEEK(CURDATE(), 1)
        GROUP BY rating_name, id_markets
    ) AS T1, (SELECT @prev_rating_name := '', @rn := 0) AS vars
    ORDER BY rating_name, good DESC
) AS T2
WHERE rn <= 2
ORDER BY rating_name, good DESC

对测试数据运行时的结果:

法国1 2 0 0
法国2 1 0 0
爱尔兰1 4 2 0
爱尔兰21 3 1 0
波兰1 3 1 0
波兰2 1 0 0


 类似资料:
  • 我目前加入了5个表来选择20个对象显示给用户,不幸的是,如果我使用和,它会变得非常慢。 查询的解释显示如下: 所以看起来它没有为表使用键,分析说明它使用2.7s复制到tmp表。 没有使用或,我尝试使用,但不幸的是,这没有改善。 我想我错过了一些基本的概念在这里和任何帮助将是感激的。 由于很可能是我弄错了表,下面是对表的描述: Objekte laender,regionen,subregionen

  • 我需要限制每分钟的请求数。我还没有找到任何方法来使用Spring云网关redis。下面是当前的实现:图像实现 customRouter.getBurstCapacitycustomRouter.getReplenishRate 两者都仅在几秒钟内运行。示例:20 个请求在同一秒内与。 我在1分钟内需要20个请求。

  • 问题内容: 上面的查询将返回前10个等级。 如何修改,或者是否存在另一种语法来查询第10位到第20位? 问题答案: 这真的是基本的东西。您应该使用: http://dev.mysql.com/doc/refman/5.5/en/select.html 两个参数10,10是(Offset,Limit),因此它将检索第11-20行。 9,11将需要获得第10-20名。

  • 我有一个表'gems'在那里存储帖子(例如blog)。对帖子的回复也存储在同一个表中,其中有一个字段存储父帖子的密钥。每个帖子都可以附上文件。 我需要得到一个与相关的回复和附加文件的帖子列表。因此“gems”有多个左联接--一个连接到它自己,一个连接到带有文件名的“gemdetail”。此查询有效: 但是,如果我每个帖子有20个回复和10个文件,那么返回的记录数是每个帖子200条。限制条款起作用,

  • 问题内容: 我正在尝试按小时使用量从历史记录表中获取报告。表是; 我想通过组和在指定日期范围内的所有记录。 我使用了类似这样的查询,但是它并不能显示全部时间。 仅在有记录时显示。 问题答案: 您现有的查询可以简化为: 要显示 每一个 小时,包括那些没有数据,就需要外,其所有您想要的数据小时表连接。您可以使用以下命令在查询中建立这样的表: 但是,对于没有数据的组的处理实际上是业务逻辑的问题,最好将其

  • 问题内容: 如果我在表中有一列具有类型字段,并且如果我尝试插入长度为16的数据,MySQL会提示错误 有谁知道为什么MySQL中的VARCHAR字段采用固定长度?另外,基于给定的大小,每个记录的VARCHAR字段会占用多少字节? 问题答案: 如果将一列设置为允许的最大字节数为15,则在不修改该列以使其支持超过15个字符的情况下,最多不能传递15个字符。如果存储4个字符串,则只能使用约4个字节可能的