MySQL 中是否有一个查询允许类似于此的可变组号和限制

MyS*_*eam 2 mysql group-by

我已经检查了一些 stackoverflow 问题,也有类似的问题,但没有完全解决这个问题。

如果你有一个这样的表:

uid    cat_uid    itm_uid
 1        1          4
 2        1          5
 3        2          6
 4        2          7
 5        3          8
 6        3          9
Run Code Online (Sandbox Code Playgroud)

其中 auto_incremented 中的 uid 列和 cat_uid 引用与过滤相关的类别,并且 itm_uid 值是我们正在寻找的值

我想获得包含以下示例结果的结果集:

array (
 0 => array (1 => array(4,5)),
 1 => array (2 => array(6,7)),
 2 => array (3 => array(8,9))
)
Run Code Online (Sandbox Code Playgroud)

一个示例问题是 - 从每个类别(无论类别有多少)中选择 2 条记录,并确保它们是这些类别中按 uid 划分的最后 2 个条目。

我不确定如何构建问题以允许答案,并且欢迎任何有关解决方案方法的提示!

编辑: 这不是一个非常明确的问题,所以让我将场景扩展到更具体的东西。

我有一组记录正在输入类别,我想通过尽可能少的查询来选择每个类别输入的最新 2 条记录,这样当我列出这些类别的内容时,我将至少有 2 条记录每个类别的记录(假设数据库中已有 2 个或更多)。有一个类似的查询,选择最后 100 条记录并将它们过滤到类别中,但对于少量类别,其中一些类别更新速度比其他类别快,可能会导致前 100 条记录不包含每个类别的成员,因此尝试为了解决这个问题,我一直在寻找一种方法,从每个类别中选择 2 条记录(或者假设每个类别相同,则选择 N 条记录),并将这 2 条记录作为最后输入的记录。日期字段可用于排序,但 itm_uid 本身可用于指示插入顺序。

nob*_*ody 5

SELECT cat_uid, itm_uid,
   IF( @cat = cat_uid, @cat_row := @cat_row + 1, @cat_row := 0 ) AS cat_row,
   @cat := cat_uid
   FROM my_table
   JOIN (SELECT @cat_row := 0, @cat := 0) AS init
   HAVING cat_row < 2
   ORDER BY cat_uid, uid DESC
Run Code Online (Sandbox Code Playgroud)

结果中将有两列额外的列,只需忽略它们即可。

这是逻辑:

我们按 cat_uid、uid 降序对表进行排序,然后从顶部开始,为每一行指定一个“行号”(cat_row),每当 cat_uid 更改时,我们都会将此行号重置为零:

---------------------------------------
|  uid  | cat_uid | itm_uid | cat_row |
|   45  |    4    |    34   |    0    |
|   33  |    4    |    54   |    1    |
|   31  |    4    |    12   |    2    |
|   12  |    4    |    51   |    3    |
|   56  |    6    |    11   |    0    |
|   20  |    6    |    64   |    1    |
|   16  |    6    |    76   |    2    |
|  ...  |   ...   |   ...   |    ...  |
---------------------------------------
Run Code Online (Sandbox Code Playgroud)

现在,如果我们只保留有的行,cat_row < 2我们就会得到我们想要的结果:

---------------------------------------
|  uid  | cat_uid | itm_uid | cat_row |
|   45  |    4    |    34   |    0    |
|   33  |    4    |    54   |    1    |
|   56  |    6    |    11   |    0    |
|   20  |    6    |    64   |    1    |
|  ...  |   ...   |   ...   |    ...  |
---------------------------------------
Run Code Online (Sandbox Code Playgroud)