mysql - 如何在 MySQL 中执行动态 UNION 查询?

标签 mysql sql

mytable 有一个自动递增的 id 列,它是一个整数,并且出于所有意图和目的在这种情况下您可以安全地假设较高的 ID 表示较新的值。 mytable 还有一个名为 group_id 的索引列,它是 groups 表的外键。

我想要一个快速而肮脏的查询来为 mytable 中的每个 group_id 选择最近的 5 行。

如果只有三个组,这会很容易,因为我可以这样做:

SELECT * FROM `mytable` WHERE `group_id` = 1 ORDER BY `id` DESC LIMIT 5 
UNION ALL 
SELECT * FROM `mytable` WHERE `group_id` = 2 ORDER BY `id` DESC LIMIT 5 
UNION ALL 
SELECT * FROM `mytable` WHERE `group_id` = 3 ORDER BY `id` DESC LIMIT 5 

但是,没有固定数量的组。组由 groups 表中的内容决定,因此组的数量不确定。

到目前为止我的想法:

  • 我可以在 groups 表上获取一个 CURSOR 并构建一个新的 SQL 查询字符串,然后 EXECUTE 它。但是,这看起来真的很麻烦,我希望有更好的方法。
  • 我可以在 groups 表上获取一个 CURSOR 并将内容插入临时表,然后从中进行选择。然而,这看起来也很乱。
  • 我不知道我是否可以只获取一个 CURSOR 然后直接从那里开始返回行。是否有类似于 SQL Server 的 @table 类型变量的东西?
  • 我最希望的是我想多了,有一种方法可以在 SELECT 语句中做到这一点。

最佳答案

要获得每组最近的 n 行,最好由其他 RDBMS(SQL Server、Postgre Sql、Oracle 等)中的窗口函数处理,但不幸的是,MySql 没有任何窗口函数,因此有一个解决方案在这种情况下,使用用户定义的变量为属于同一组的行分配排名 ORDER BY group_id,id desc对每组正确排序结果很重要

SELECT  c.*
FROM (
SELECT *,
@r:= CASE WHEN @g = group_id THEN @r + 1 ELSE 1 END rownum,
@g:=group_id
FROM mytable
CROSS JOIN(SELECT @g:=NULL ,@r:=0) t
  ORDER BY group_id,id desc
) c
WHERE c.rownum <=5

上面的查询将为每个 group_id 提供 5 个最近的行如果你想获得超过 5 行,只需将外部查询的 where 过滤器更改为你想要的数字 WHERE c.rownum <= n

关于mysql - 如何在 MySQL 中执行动态 UNION 查询?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26633907/

相关文章:

sql - 使用可选参数运行 SQL 查询的最佳方式是什么?

mysql - 如何使用 LIKE mysql 匹配列中的文本

mysql - 在 MySQL 中使用分区选择重复项?

mysql - 将文件保存为 MYSQL 数据库中的 blob 或文件路径

sql - 存储过程是否有助于消除 SQL 注入(inject)/存储过程与应用程序中的普通 SQL 语句相比有何优势?

MySQL:根据A表和B表的数据更新表A

mysql - 1205 错误 : table still locked after a lot of time

mysql - 将列从 varchar 更改为时间戳,保留值

mysql - 使用宏删除mysql表条目

sql - SQL Server 中 "WITH SCHEMABINDING"的缺点?