我有一个像这样的表A:
ID | AMOUNT
1 | 10
2 | 30
3 | 40
我想找到行的总和等于一个值。
例如,如果我将总数设为70,则查询必须返回ID 2和3
答案 0 :(得分:0)
以下查询将返回两行的列表,其总和等于您传递的值。如果匹配总和的行组合超过一个,它将返回多个列表。在Fiddle上进行检查。您只需要传递所需的总金额,而不是 70
SELECT If((t1.amount+t2.amount)=6,CONCAT(LEAST(t1.id,t2.id),',',GREATEST(t1.id,t2.id)),"") AS sumIds
FROM testSum t1, testSum t2
WHERE (t1.amount+t2.amount)=6
AND t1.id!=t2.id
GROUP BY sumIds
答案 1 :(得分:0)
您知道每一行的链接行的值应该是多少(70量),因此,给定这一行,您可以为每一行生成最小和最大数量,并基于该块中的minamount和行号生成一个blockid。例如给出的
+------+--------+
| 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;
你得到
+-------+-----------+-----------+---------+-----------+------+
| 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)
如果您再次执行相同的操作,并且在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;
您得到
+-------+-----------+-----------+---------+-----------+-------+-----------+-----------+---------+-----------+
| 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)
在版本8或更高版本中,可以使用row_number函数简化行号模拟