Mysql选择总和等于的行
我有一张这样的桌子:Mysql选择总和等于的行,mysql,Mysql,我有一张这样的桌子: ID | AMOUNT 1 | 10 2 | 30 3 | 40 我想找到金额总和等于某个值的行 例如,如果我将总数设置为70,则我的查询必须返回ID2和ID3,下面的查询将返回两行的列表,其总和等于您传递的值。如果有多个行组合与total sum匹配,它将返回多个列表。看看这个。您只需要通过所需的总和,而不是70 您知道每一行的链接行的值应该是多少(70个数量),因此您可以为每一行生成最小和最大数量,并基于块内的最小装载量和行数生成块ID。举个例子 +------
ID | AMOUNT
1 | 10
2 | 30
3 | 40
我想找到金额总和等于某个值的行
例如,如果我将总数设置为70,则我的查询必须返回ID2和ID3,下面的查询将返回两行的列表,其总和等于您传递的值。如果有多个行组合与total sum匹配,它将返回多个列表。看看这个。您只需要通过所需的总和,而不是70
您知道每一行的链接行的值应该是多少(70个数量),因此您可以为每一行生成最小和最大数量,并基于块内的最小装载量和行数生成块ID。举个例子
+------+--------+
| id | amount |
+------+--------+
| 1 | 10 |
| 2 | 30 |
| 3 | 40 |
| 4 | 70 |
| 5 | 35 |
| 6 | 35 |
| 7 | 35 |
| 8 | 35 |
| 9 | 40 |
| 10 | 60 |
| 11 | 60 |
+------+--------+
11 rows in set (0.00 sec)
select id oldid,amount,
70 - amount matching_amount,
case when amount = 70 then 0
when amount < 70 - amount then amount
when amount >= 70 - amount then 70 - amount
end as minamount,
case when amount = 70 then amount
when amount < 70 - amount then 70 - amount
when amount >= 70 - amount then amount
end as maxamount
from t
) s
cross join (select @bn:=0,@rn:=0,@pid:=0,@pmin:=999999) b
order by minamount,oldid;
如果再次执行相同操作,并在blockid中左键连接奇数到偶数行
select x.oldid,x.minamount,x.maxamount,x.blockid,x.rownumber, y.oldid,
y.minamount,y.maxamount,y.blockid,y.rownumber
from
(
select oldid,minamount,maxamount,
if(minamount <> @pmin,@bn:=@bn+1,@bn:=@bn) blockid,
if(minamount <> @pmin,@rn:=1,@rn:=@rn+1) rownumber,
@pmin:=minamount pmin
from
(
select id oldid,amount,
70 - amount matching_amount,
case when amount = 70 then 0
when amount < 70 - amount then amount
when amount >= 70 - amount then 70 - amount
end as minamount,
case when amount = 70 then amount
when amount < 70 - amount then 70 - amount
when amount >= 70 - amount then amount
end as maxamount
from t
) s
cross join (select @bn:=0,@rn:=0,@pid:=0,@pmin:=999999) b
order by minamount,oldid
) x
left join
(
select oldid,minamount,maxamount,
if(minamount <> @pmin1,@bn1:=@bn1+1,@bn1:=@bn1) blockid,
if(minamount <> @pmin1,@rn1:=1,@rn1:=@rn1+1) rownumber,
@pmin1:=minamount pmin
from
(
select id oldid,amount,
70 - amount matching_amount,
case when amount = 70 then 0
when amount < 70 - amount then amount
when amount >= 70 - amount then 70 - amount
end as minamount,
case when amount = 70 then amount
when amount < 70 - amount then 70 - amount
when amount >= 70 - amount then amount
end as maxamount
from t
) a
cross join (select @bn1:=0,@rn1:=0,@pid1:=0,@pmin1:=999999) b
order by minamount,oldid
) y
on y.blockid = x.blockid and y.rownumber = x.rownumber + 1
where (x.rownumber % 2 > 0 and y.oldid is not null) or
(x.rownumber % 2 > 0 and x.minamount = 0)
order by x.oldid;
在版本8或更高版本中,可以使用行数函数简化行数模拟我的查询必须返回id。。。你的问题在哪里?有什么问题吗?这需要暴力手段,因此我认为应该在编程级别进行。另外,如果已经有一行
amount
为70
,该怎么办?在这种情况下需要什么输出?我只想返回两行匹配的内容。如果已经有一行金额为70,则我的qery必须返回这一行或第2行和第3行,假设您有3行金额为35。您应该返回1行还是2行?
+-------+-----------+-----------+---------+-----------+------+
| oldid | minamount | maxamount | blockid | rownumber | pmin |
+-------+-----------+-----------+---------+-----------+------+
| 4 | 0 | 70 | 1 | 1 | 0 |
| 1 | 10 | 60 | 2 | 1 | 10 |
| 10 | 10 | 60 | 2 | 2 | 10 |
| 11 | 10 | 60 | 2 | 3 | 10 |
| 2 | 30 | 40 | 3 | 1 | 30 |
| 3 | 30 | 40 | 3 | 2 | 30 |
| 9 | 30 | 40 | 3 | 3 | 30 |
| 5 | 35 | 35 | 4 | 1 | 35 |
| 6 | 35 | 35 | 4 | 2 | 35 |
| 7 | 35 | 35 | 4 | 3 | 35 |
| 8 | 35 | 35 | 4 | 4 | 35 |
+-------+-----------+-----------+---------+-----------+------+
11 rows in set (0.00 sec)
select x.oldid,x.minamount,x.maxamount,x.blockid,x.rownumber, y.oldid,
y.minamount,y.maxamount,y.blockid,y.rownumber
from
(
select oldid,minamount,maxamount,
if(minamount <> @pmin,@bn:=@bn+1,@bn:=@bn) blockid,
if(minamount <> @pmin,@rn:=1,@rn:=@rn+1) rownumber,
@pmin:=minamount pmin
from
(
select id oldid,amount,
70 - amount matching_amount,
case when amount = 70 then 0
when amount < 70 - amount then amount
when amount >= 70 - amount then 70 - amount
end as minamount,
case when amount = 70 then amount
when amount < 70 - amount then 70 - amount
when amount >= 70 - amount then amount
end as maxamount
from t
) s
cross join (select @bn:=0,@rn:=0,@pid:=0,@pmin:=999999) b
order by minamount,oldid
) x
left join
(
select oldid,minamount,maxamount,
if(minamount <> @pmin1,@bn1:=@bn1+1,@bn1:=@bn1) blockid,
if(minamount <> @pmin1,@rn1:=1,@rn1:=@rn1+1) rownumber,
@pmin1:=minamount pmin
from
(
select id oldid,amount,
70 - amount matching_amount,
case when amount = 70 then 0
when amount < 70 - amount then amount
when amount >= 70 - amount then 70 - amount
end as minamount,
case when amount = 70 then amount
when amount < 70 - amount then 70 - amount
when amount >= 70 - amount then amount
end as maxamount
from t
) a
cross join (select @bn1:=0,@rn1:=0,@pid1:=0,@pmin1:=999999) b
order by minamount,oldid
) y
on y.blockid = x.blockid and y.rownumber = x.rownumber + 1
where (x.rownumber % 2 > 0 and y.oldid is not null) or
(x.rownumber % 2 > 0 and x.minamount = 0)
order by x.oldid;
+-------+-----------+-----------+---------+-----------+-------+-----------+-----------+---------+-----------+
| oldid | minamount | maxamount | blockid | rownumber | oldid | minamount | maxamount | blockid | rownumber |
+-------+-----------+-----------+---------+-----------+-------+-----------+-----------+---------+-----------+
| 1 | 10 | 60 | 2 | 1 | 10 | 10 | 60 | 2 | 2 |
| 2 | 30 | 40 | 3 | 1 | 3 | 30 | 40 | 3 | 2 |
| 4 | 0 | 70 | 1 | 1 | NULL | NULL | NULL | NULL | NULL |
| 5 | 35 | 35 | 4 | 1 | 6 | 35 | 35 | 4 | 2 |
| 7 | 35 | 35 | 4 | 3 | 8 | 35 | 35 | 4 | 4 |
+-------+-----------+-----------+---------+-----------+-------+-----------+-----------+---------+-----------+
5 rows in set (0.10 sec)