我有一个复杂的查询(包含多个连接、联合),它返回一组包含id、day、hr、amount的行。查询的输出如下所示:
id day hr amount
1 1 1 10
1 1 2 25
1 1 3 30
1 2 1 10
1 2 2 40
1 2 2 30
2 1 1 10
2 1 2 15
2 1 3 30
2 2 1 10
2 2 2 20
2 2 2 30
我需要找到每个id的累积总数,每天的每小时。输出应该是这样的:
id day hr amount cumulative total
1 1 1 10 10
1 1 2 25 35
1 1 3 30 65
1 2 1 10 10
1 2 2 40 50
1 2 2 30 80
2 1 1 10 10
2 1 2 15 25
2 1 3 30 55
2 2 1 10 10
2 2 2 20 30
2 2 2 30 60
生成第一个输出的初始查询如下所示:
select id, day, hr, amount from
( //multiple joins on multiple tables)a
left join
(//unions on multiple tables)b
on a.id=b.id;
SQL查询是什么来获得第二个输出中描述的累积和的?不应在溶液中使用SET。
谢谢。
3条答案
按热度按时间svmlkihl1#
MySQL 8.0引入了“窗口函数”,功能等同于SQL Server“窗口函数”(由Transact-SQL
OVER
语法提供分区和排序)和Oracle“分析函数”。它现在还支持CTE。12.第十二章21窗口功能https://dev.mysql.com/doc/refman/8.0/en/window-functions.html
这里提供的答案是针对MySQL 8之前版本的方法。0.
MySQL不提供类型分析函数,您可以使用它来获取运行的“累积和”,就像其他DBMS(如Oracle或SQL Server)中可用的分析函数一样。)
但是,可以使用MySQL模拟一些分析函数。
至少有两种可行的方法:
一种是使用相关子查询来获得小计。这种方法在大型集合上的开销可能很大,如果外部查询上的 predicate 很复杂,则会很复杂。这实际上取决于“多个表上的多个连接”有多复杂。(MySQL也不支持CTE。)
另一种方法是利用MySQL用户变量,进行一些控制中断处理。这里的“技巧”是对查询的结果进行排序(使用ORDER BY),然后将查询 Package 在另一个查询中。
我将给予一个后一种方法的例子。
由于MySQL执行操作的顺序,在将当前行的
id
和day
的值保存到用户变量中之前,需要计算cumulative_total
列。把这一栏放在第一位是最简单的。别名为i的内联视图(在下面的查询中)只是用来初始化用户变量,以防这些变量已经在会话中设置。如果已经为它们赋值,我们希望忽略它们的当前值,最简单的方法是初始化它们。
您的原始查询被 Package 在括号中,并在下面的示例中被赋予一个别名
c
。对原始查询的唯一更改是添加了ORDERBY子句,因此可以确保按顺序处理查询中的行。外部选择检查当前行的
id
和day
值是否与前一行“匹配”。如果是,我们将当前行的amount
添加到累计小计中。如果它们不匹配,那么我们将累计小计重置为零,并添加当前行的金额(或者更简单地说,只是分配当前行的金额)。在我们完成了累积总数的计算之后,我们将当前行的
id
和day
值保存到用户变量中,以便在处理下一行时可以使用它们。例如:
如果有必要以不同的顺序返回列,累积总计作为最后一列,那么一种选择是将整个语句 Package 在一组括号中,并将该查询用作内联视图:
dxxyhpgq2#
如果您使用的是MySQL 8或更高版本,则应该使用window functions。您的查询将为:
其中
t
是您的表b
左连接到a
。一些注意事项:PARTITION BY
子句保证您获得每个id
和day
的累计和,因此每天我们都重新开始求和ORDER BY
子句定义了累积的发生顺序kkih6yb83#
给你,这是你最后的总数。..