如何在 MySQL 中执行复杂的 GROUP BY?

Mic*_*wan 8 mysql order-by random

我有一个表,其中包含进入其他表的几个键(其中每个键由多列组成)。我希望能够将具有相同键的行组合在一起,但我不想将所有行组合在一起。这不是一个简单GROUP BY的键,而是我希望能够分组说 10。所以如果一个特定的键出现 50 次,当我进行这个分组时我会得到 5 个结果(5 组,每组 10 个)。我还希望此分组在密钥内随机发生。

我不知道这样做的直接方法,而且我想出的迂回方法并没有像我认为的那样工作。我想出的迂回解决方案是为每个键创建一个新列,该列将是一个整数,以便值i表示该ith键的出现(但以随机顺序)。然后我可以进行整数除法,以便键中的每 n(比如 10)行具有相同的值,并且我可以GROUP BY对该值执行 a 。

有没有更直接的方法来完成我刚刚描述的事情?这很尴尬,我在创建新索引列时遇到了问题(正如我在这个问题中所描述的)。

编辑:首先请注意,这是针对 MySQL 的。如果我的目标不明确,我将添加一个示例。MySQL 文档显示了一种几乎可以到达的方法:

CREATE TABLE animals (
    grp ENUM('fish','mammal','bird') NOT NULL,
    id MEDIUMINT NOT NULL AUTO_INCREMENT,
    name CHAR(30) NOT NULL,
    PRIMARY KEY (grp,id)
) ENGINE=MyISAM;

INSERT INTO animals (grp,name) VALUES
    ('mammal','dog'),('mammal','cat'),
    ('bird','penguin'),('fish','lax'),('mammal','whale'),
    ('bird','ostrich');

SELECT * FROM animals ORDER BY grp,id;
Run Code Online (Sandbox Code Playgroud)

这将创建一个表,虽然不是我想要的,但它很接近:

+--------+----+---------+
| grp    | id | name    |
+--------+----+---------+
| fish   |  1 | lax     |
| mammal |  1 | dog     |
| mammal |  2 | cat     |
| mammal |  3 | whale   |
| bird   |  1 | penguin |
| bird   |  2 | ostrich |
+--------+----+---------+
Run Code Online (Sandbox Code Playgroud)

我基本上想要GROUP BYid,除了我希望记录mammal有一个“组”用于 ID 1-10,另一个“组”用于 ID 11-20,等等。但是,我将使用现有表来执行此操作,而且我不一定希望“狗”以 ID 1 出现。我希望初始排序是随机的,但随后是确定性的。

小智 5

对您的 ID 列进行一些数学运算以动态生成组怎么样?

SELECT grp, FLOOR(id/10) AS id_grp
FROM animals
GROUP BY grp, id_grp
Run Code Online (Sandbox Code Playgroud)

这将根据记录的 ID 为您提供 10 组。我使用上面的动物表来生成下面的数据。

样本数据

 INSERT INTO animals VALUES
 ('mammal',10,'dog'),('mammal',11,'dog'),('mammal',12,'dog'),
 ('mammal',21,'cat'),('mammal',22,'cat'),('mammal',23,'cat'),
 ('mammal',24,'cat'),('mammal',25,'cat'),('mammal',26,'cat'),
 ('bird',30,'penguin'),('bird',31,'penguin'),('bird',32,'penguin'),
 ('bird',33,'penguin'),('fish',44,'lax'),('fish',45,'lax'),
 ('fish',46,'lax'),('fish',47,'lax'),('fish',48,'lax'),
 ('mammal',31,'whale'),*'fish',51,'lax'),('fish',52,'lax'),
 ('fish',53,'lax'),('fish',54,'lax'),('bird',10,'ostrich');
Run Code Online (Sandbox Code Playgroud)

查询输出

 +--------+--------+
 | grp    | id_grp |
 +--------+--------+
 | fish   |      4 |
 | fish   |      5 |
 | mammal |      1 |
 | mammal |      2 |
 | mammal |      3 |
 | bird   |      1 |
 | bird   |      3 |
 +--------+--------+
 7 rows in set (0.00 sec)
Run Code Online (Sandbox Code Playgroud)


gbn*_*gbn 2

在 SQL 中,通常是这样的:

  • 一个 DISTINCT 子选择
  • 通过 DISTINCT 键 JOIN 返回主表
  • NTILE 在 DISTINCT 键上使用 PARTITION BY 并使用 ORDER BY 创建存储桶

它不是聚合,因此不需要 GROUP BY

编辑:

实际上,NTILE本身就足以创建“每组不同值的 n 个桶”

  • @gbn 不是 MySQL 是我应该澄清的一点。文章引用了 Oracle。 (2认同)