Mysql 从总和小于值的表中获取行
假设表中有以下行Mysql 从总和小于值的表中获取行,mysql,sum,mariadb,having,mysql-5.7,Mysql,Sum,Mariadb,Having,Mysql 5.7,假设表中有以下行 | id | user_id | amount | date | ------------------------------------------------ | 1 | 1 | 100 | 2019-09-30 | ------------------------------------------------ | 2 | 2 | 100 | 2019-09-30
| id | user_id | amount | date |
------------------------------------------------
| 1 | 1 | 100 | 2019-09-30 |
------------------------------------------------
| 2 | 2 | 100 | 2019-09-30 |
------------------------------------------------
| 3 | 1 | 100 | 2019-09-30 |
------------------------------------------------
| 4 | 3 | 100 | 2019-10-01 |
------------------------------------------------
| 5 | 1 | 75 | 2019-10-01 |
------------------------------------------------
| 6 | 3 | 100 | 2019-10-01 |
------------------------------------------------
| 7 | 1 | 35 | 2019-10-01 |
------------------------------------------------
我正在试图找到一种方法来获取所有user_id=1的行,其中summatum<300,date是一个滚动求和问题。在MySQL 8.0.2及更高版本中,您可以使用。在旧版本中,我们可以使用用户定义的会话变量执行相同的操作 我们首先使用。 然后,使用a中的结果集,并找到total sum跨越300界限的id。当新滚动总和大于300时,达到屏障。此时,我们将barrier值设置为1,前面的行设置为0,后面的行设置为2或更多。 我们只考虑障碍物为0的行。 Try适用于所有MySQL版本: 问题1
如果您不喜欢使用一些有经验的会话变量,因此用户非常不喜欢它们,那么您可以使用基于自连接的技术,然后使用GROUP BY进行过滤 一般的想法是,我们离开join以获取特定用户id的前几行,然后聚合以获得滚动和,然后使用Having子句进行过滤 质疑 您可以对这两种方法进行基准测试,并决定哪一种是合适的
对于此查询,您将需要复合索引:user_id,date在预期输出中,您将获得对应于10月1日的行,但您的条件是date<10月1日。此外,日期<'2019-09-31'-没有9月31日这样的事情。请修复问题声明。另外,您的MySQL服务器版本是什么?运行选择版本@MadhurBhaiya,谢谢你注意到了。我确实向该数据添加了更多行,但没有更新问题陈述。我也添加了版本。检查谢谢,我会看一看。谢谢你的回答,谢谢。这个查询的性能如何?我们是否需要在考虑此查询的任何列上添加索引?此表每天接收近50k条记录,此查询检索到的实际行数可能为每个用户150多行。@Abishek索引取决于您的WHERE条件。例如,在当前查询中,如果要筛选特定的用户和日期范围,则需要一个复合索引:user_id,date。列的顺序在这里很重要。关于一般性能,此查询将具有与窗口函数技术类似的性能;我认为它对于旧版本的MySQL非常好。同样的问题也适用于这个查询。如果我将阈值限制设置为180,它只返回第1行,而不是第1行和第5行。不确定是否存在任何通信错误。我的问题陈述是,我正在试图找到一种方法来获取user_id=?的所有行?金额在哪里?和date@Abishek您可以在某些存储过程中执行此操作。但在一天结束时,它将是一个循环,然后一些if-else检查哪一个最适合。我会再作考虑,;如果我发现了一些问题,请告诉我最新情况,我非常感谢花时间为这个问题添加另一个答案。很高兴知道我可以在没有会话变量的情况下完成这项工作。我将研究这两种方法,从性能角度看哪一种效果更好。@Abishek不客气。一定要让别人知道哪个更有效;或者两者都好;或者两者都不好。如果两者都不好,也许我们可以研究出更多的技术,但我把赌注押在会话变量上。我确实看到了这个查询导致的结果返回的问题。HAVING子句设置为<300时,它返回正确的结果。但是如果我将HAVING子句更改为<180,它将返回一个不正确的结果。它应该显示2行,数量为100、75,但它只返回1行。这里是DB Fiddle@Abishek,查询中没有问题。仔细检查输入数据。2019-09-30上的用户_id=1有两行,其值等于100。检查id值:1,2。因此,在到达值为75的行之前,它们的总数=100+100=200已经跨越了180个障碍。但是对于满足日期条件的同一用户,还有第6行的值为75。这不也应该是它的一部分吗
| id | user_id | amount | date |
------------------------------------------------
| 1 | 1 | 100 | 2019-09-30 |
------------------------------------------------
| 3 | 1 | 100 | 2019-09-30 |
------------------------------------------------
| 5 | 1 | 75 | 2019-10-01 |
------------------------------------------------
SELECT dt.id,
dt.user_id,
dt.amount,
dt.date
FROM
(
SELECT
t.id,
t.user_id,
t.amount,
t.date,
@barrier := CASE
WHEN
(@tot_qty := @tot_qty + t.amount) > 300
THEN (@barrier + 1)
ELSE 0
END AS barrier
FROM
your_table AS t
CROSS JOIN (SELECT @tot_qty := 0,
@barrier := 0) AS user_init
WHERE t.user_id = 1
AND t.date <= '2019-10-01'
ORDER BY t.user_id, t.date, t.id
) AS dt
WHERE dt.barrier = 0
ORDER BY dt.user_id, dt.date, dt.id;
| id | user_id | amount | date |
| --- | ------- | ------ | ---------- |
| 1 | 1 | 100 | 2019-09-30 |
| 3 | 1 | 100 | 2019-09-30 |
| 5 | 1 | 75 | 2019-10-01 |
SELECT
t1.*
FROM
your_table AS t1
LEFT JOIN your_table AS t2
ON t2.user_id = t1.user_id
AND t2.date <= t1.date
AND t2.id <= t1.id
WHERE t1.user_id = 1
AND t1.date <= '2019-10-31'
GROUP BY t1.user_id, t1.date, t1.id, t1.amount
HAVING COALESCE(SUM(t2.amount),0) < 300;
| id | user_id | amount | date |
| --- | ------- | ------ | ---------- |
| 1 | 1 | 100 | 2019-09-30 |
| 3 | 1 | 100 | 2019-09-30 |
| 5 | 1 | 75 | 2019-10-01 |