Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/59.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Mysql 从总和小于值的表中获取行_Mysql_Sum_Mariadb_Having_Mysql 5.7 - Fatal编程技术网

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 |