Mysql-Cross join 用户自定义变量 根据输入值,查询总和小于等于输入值的记录

Mysql-Cross join 用户自定义变量 根据输入值,查询总和小于等于输入值的记录

在开发中遇到的一个需求,来记录一下方案和遇到的问题

需求场景

因为公司资金问题,需要在公司的后台管理中,输入具体的打款金额,来根据用户的提现优先级进行打款,也就是说有 A>B>C>D…等级, 在页面上输入能够打款的金额,来按照优先级进行打款,打款金额不能超过具体输入的金额,然后查出匹配的数据调用第三方平台进行打款。

		假设表中有4条提现数据
		4条数据对应的金额和等级
		amount:level
		12、  A;
		43、  S;
		54、  B;
		75、  C;
		例1:输入值:60   结果值:43,12
		例2:输入值:100  结果值:43,12
		例3:输入值:200  结果值:43,12,53,73
SQL实现
SELECT a.id, a.level , a.amount
        FROM (select ar.id, ar.level, ar.amount, (@sum := @sum + amount) as totalSum
              from table1 ar
              ORDER BY level ) a
                 cross join (select @sum := 0) params
        WHERE totalSum < 100;
实现思路
  1. @sum 自定义一个mysql 变量。
  2. 然后是用 cross join 来进行一个乘积连接。
  3. 根据输入金额做为where条件。

cross join(笛卡尔连接)

cross join是mysql中的一种连接方式,区别于内连接和外连接,对于cross join连接来说,其 实使用的就是笛卡尔连接。在MySQL中,当CROSS JOIN不使用WHERE子句时,CROSS JOIN产生了一个结果集,该结果集是两个关联表的行的乘积。通常,如果每个表分别具有n和m行,则结果集将具有n*m行

引用https://www.w3resource.com/mysql/advance-query-in-mysql/mysql-cross-join.php的图片,如图演示了cross join的过程,这个过程其实就是笛卡尔连接查询

在这里插入图片描述

测试时出现的问题:

当执行sql时,偶尔会查询不出数据来(数据是没有问题的,就是查询不出来)

经排查,最终怀疑是 @sum := 0 的问题,怀疑是Mysql的优化器对执行的sql优化时,把变量给优化掉了,导致sql不按照原有的方式执行了

解决方案

后来调整了一下cross join 连接的顺序, 将自定义变量的select 调整在前面,问题就可以解决了。

SELECT a.id, a.level , a.amount
        FROM (select @sum := 0) params
              cross join (select ar.id, ar.level, ar.amount, (@sum := @sum + amount) as totalSum
              from table1 ar
              ORDER BY level ) a 
        WHERE totalSum < 100;
下面是关于自定义变量的属性和限制
  1. 使用自定义变量的查询,无法使用查询缓存。
  2. 不能在使用常量或者标识列的地方使用自定义变量,例如表名、列明和LIMIT子句中。
  3. 用户自定义变量的生命周期是在一个连接中有效,所以不能使用它们来做连接间的通信。
  4. 如果使用连接池或者持久化连接,自定义变量可能让看起来毫无关系的代码发生交互。
  5. 在5.0版本之前,是大小写敏感的,所以要注意代码在不同版本之间的兼容性问题。
  6. 不能显示的声明自定义变量的类型。它是一个动态类型。整数初始化为0,浮点型初始化为0.0,字符串初始化为’’。
  7. MySQL优化器在某些场景下可能会将这些变量优化掉,这可能导致代码不按预想的方式运行。
  8. 赋值的顺序和赋值的时间点并不总是固定的,这依赖于优化器的决定。
  9. 赋值符号:=的优先级非常低,所有要注意赋值表达式应该使用明确的括号。
  10. 使用未定义变量不会产生任何错误,如果没有意识到这一点,非常容易犯错

用户自定义变量,是真的香。

参考文章:

Mysql自定义变量的使用

MySQL应用之CROSS JOIN用法简介教程

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值