mysql - 获取MySQL数据库前N行的运行频率分布

标签 mysql sql database frequency

我有一个 MySQL 数据库,其中一列包含状态代码。该列的类型为 int,其值只会是 100,200,300,400。看起来像下面;为清楚起见,删除了其他列。

id   |  status
----------------
 1      300
 2      100
 3      100
 4      200
 5      300
 6      300
 7      100
 8      400
 9      200
10      300
11      100
12      400
13      400
14      400
15      300
16      300

id 字段是自动生成的,并且始终是连续的。我想要第三列显示前 10 行状态代码的频率分布的逗号分隔字符串。它应该看起来像这样。

id   |  status  |  freq
-----------------------------------
 1      300
 2      100
 3      100
 4      200
 5      200
 6      300
 7      100
 8      400
 9      300
10      300
11      100       300,100,200,400    -- from rows 1-10
12      400       100,300,200,400    -- from rows 2-11
13      400       100,300,200,400    -- from rows 3-12
14      400       300,400,100,200    -- from rows 4-13
15      300       400,300,100,200    -- from rows 5-14
16      300       300,400,100        -- from rows 6-15

我想首先列出最频繁的代码。在两个状态代码具有相同频率的情况下,哪个先列出对我来说无关紧要,但我确实在示例中将较小的代码列在较大的代码之前。最后,如果代码在前十行中根本没有出现,那么它也不应列在频率列中。

非常清楚,出现频率字符串的行号考虑该行的状态代码;它只是前几行。

那我做了什么?我对 SQL 很陌生。我是一名程序员,我发现使用这种 SQL 语言有点奇怪。我管理了以下自连接选择语句。

select *, avg(b.status) freq
from sample a
join sample b
on (b.id < a.id) and (b.id > a.id - 11)
where a.id > 10
group by a.id;

使用聚合函数 avg,我至少可以证明这个概念。派生表 b 为 avg 函数提供了正确的行,但我无法弄清楚对 b 中的行进行计数和分组以获得频率分布,然后将频率行折叠为单个字符串值的多步骤过程。

我也曾尝试使用标准存储函数和过程来代替内置聚合函数,但似乎 b 派生表超出了范围之类的。我似乎无法访问它。据我所知,编写自定义聚合函数对我来说是不可能的,因为它似乎需要用 C 语言进行开发,而我没有接受过这样的培训。

这是加载示例的 sql。

create table sample (
    id int NOT NULL AUTO_INCREMENT,
    PRIMARY KEY(id),
    status int
);

insert into sample(status) values(300),(100),(100),(200),(200),(300)
  ,(100),(400),(300),(300),(100),(400),(400),(400),(300),(300),(300)
  ,(100),(400),(100),(100),(200),(500),(300),(100),(400),(200),(100)
  ,(500),(300);

示例有 30 行数据可供使用。我知道这是一个很长的问题,但我只是想尽可能详细。我已经为此工作了几天,真的很想完成它。

感谢您的帮助。

最佳答案

我知道的唯一方法就是使用 BEFORE INSERT 触发器。它必须是 BEFORE INSERT,因为您想要更新正在插入的行中的值,这只能在 BEFORE 触发器中完成。不幸的是,这也意味着它还没有被分配一个 ID,所以希望可以安全地假设在插入新记录时,表中的最后 10 条记录是你感兴趣的。你的触发器将需要获取最后 10 个 ID 的值并使用 GROUP_CONCAT 函数将它们连接成一个字符串,按 COUNT 排序。我主要使用 SQL Server,目前无法访问 MySQL 服务器来对此进行测试,但希望我的语法足够接近,至少可以让您朝着正确的方向前进:

create trigger sample_trigger BEFORE INSERT ON sample 
FOR EACH ROW
BEGIN
    DECLARE _freq varchar(50);

    SELECT GROUP_CONCAT(tbl.status ORDER BY tbl.Occurrences) INTO _freq
    FROM (SELECT status, COUNT(*) AS Occurrences, 1 AS grp FROM sample ORDER BY id DESC LIMIT 10) AS tbl
    GROUP BY tbl.grp

    SET new.freq = _freq;
END

关于mysql - 获取MySQL数据库前N行的运行频率分布,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5738503/

相关文章:

php - 如何以 2 组为一组回显结果?

sql - ADODB 奇怪的行为

php - 快速 PHP 变量指南

mysql - 复合键错误代码 : 1822 when data types are matching,

PHP 通知 : Array to string conversion in and Unsupported operand types in

mysql - 如何计算等于或加起来等于某个时移的记录?

c# - 在 C# 应用程序中使用 SQL 的最简单方法?

mysql - 在 MySql 中获取具有两列最大值的行

sql - 使用 Group BY 选择后删除 ID

mysql - 当我使用完全相同的查询定位不同的列时,查询不起作用