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)