如何在 mysql 中查找具有多行总和的 ID?
How to find ids with sum of multiple rows in mysql?
这是我的 mysql table.
CREATE TABLE IF NOT EXISTS tbl_money (
id int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
amount int(11) NOT NULL,
used int(11) NOT NULL
) ENGINE=InnoDB AUTO_INCREMENT=15 DEFAULT CHARSET=latin1;
INSERT INTO tbl_money ( id , amount , used ) VALUES
(8, 2, 0),
(9, 4, 0),
(10, 4, 0),
(11, 3, 0),
(12, 8, 0),
(13, 10, 0),
(14, 13, 0);
Id 是一个主键字段,money 可以是从 1 到任意数字的任意数字。
问题:
假设我必须从数量为 8 的 table 中找到 id。这很简单,因为 id 5 包含数量 8。但是如果我必须找到数量为 14 的不存在的 id。我现在必须 select 2 个或更多字段,总和等于 14。例如在上面 table 我可以 select id 6 和 id 3 总和等于 14。就像我需要找到 6 我必须 select id 1 和 2 因为它们的总和等于 6。
有时我们可能需要 select 超过 2 行才能使总和相等。但是如果任何条件不匹配 table 的所有行,我们可以 return 0.
条件:
已被占用的行不能再次 selected。使用的字段应始终为 0。如果使用的字段值为 1,我们不能 select 它。我们只会搜索偶数,所以我们不需要担心奇数。
请建议我如何解决这个算法。提前致谢。
以下只是一个想法,尝试在函数或SP中实现它。
想法一:
我。判断得到的值是ODD还是EVEN。
二。如果是偶数,则尝试在您的帐户中添加 两个偶数 号码或 两个奇数 号码
table 并检查它是否符合您的值。
三。如果是奇数,则尝试从 table 中添加 一个偶数 号码和 一个奇数 号码并检查它是否与您的值匹配。
四。如果你没有得到结果,那么
- 如果是偶数,加三个偶数个数
- 如果是奇数,添加三个奇数 号码或两个偶数 号码和一个奇数 号码
思路二:(这会很简单)
我。从样本数据中取 first 值,取值 2
并添加其他行值,例如 2+4 == 14, 2+4 == 14, 2+3 == 14, 2+8 == 14, 2+10 == 14, 2+13 == 14
二。然后取 第二行值 说值 4
并添加其他值,如 4+4 == 14, 4+3 == 14, 4+8 == 14, 4+10== 14, 4+13 == 14
。这里 4+10
匹配值 14
。 (如果您需要所有组合,则继续执行,否则中断此执行)。
三。一旦 10+13
组合完成,然后添加前两个值并添加其他值,例如 6+4, 6+3, 6+8, 6+10, 6+13
四。继续直到组合 31(2+4+4+3+8+10)+13
希望对您有所帮助。
纯粹的 SQL 方法,可能效率不高:-
SELECT CONCAT_WS(',', a.id, b.id, c.id, d.id)
FROM tbl_money a
INNER JOIN tbl_money b ON b.id > a.id
INNER JOIN tbl_money c ON c.id > b.id
INNER JOIN tbl_money d ON d.id > c.id
WHERE a.amount + b.amount + c.amount + d.amount = 14
UNION
SELECT CONCAT_WS(',', a.id, b.id, c.id)
FROM tbl_money a
INNER JOIN tbl_money b ON b.id > a.id
INNER JOIN tbl_money c ON c.id > b.id
WHERE a.amount + b.amount + c.amount = 14
UNION
SELECT CONCAT_WS(',', a.id, b.id)
FROM tbl_money a
INNER JOIN tbl_money b ON b.id > a.id
WHERE a.amount + b.amount = 14
UNION
SELECT a.id
FROM tbl_money a
WHERE a.amount = 14
编辑 - 修改以检查使用的字段,并且金额不是奇数
SELECT CONCAT_WS(',', a.id, b.id, c.id, d.id)
FROM tbl_money a
INNER JOIN tbl_money b ON b.id > a.id AND b.used = 1 AND MOD(b.amount, 2) = 0
INNER JOIN tbl_money c ON c.id > b.id AND c.used = 1 AND MOD(c.amount, 2) = 0
INNER JOIN tbl_money d ON d.id > c.id AND d.used = 1 AND MOD(d.amount, 2) = 0
WHERE a.amount + b.amount + c.amount + d.amount = 14
AND a.used = 1
AND MOD(a.amount, 2) = 0
UNION
SELECT CONCAT_WS(',', a.id, b.id, c.id)
FROM tbl_money a
INNER JOIN tbl_money b ON b.id > a.id AND b.used = 1 AND MOD(b.amount, 2) = 0
INNER JOIN tbl_money c ON c.id > b.id AND c.used = 1 AND MOD(c.amount, 2) = 0
WHERE a.amount + b.amount + c.amount = 14
AND a.used = 1
AND MOD(a.amount, 2) = 0
UNION
SELECT CONCAT_WS(',', a.id, b.id)
FROM tbl_money a
INNER JOIN tbl_money b ON b.id > a.id AND b.used = 1 AND MOD(b.amount, 2) = 0
WHERE a.amount + b.amount = 14
AND a.used = 1
AND MOD(a.amount, 2) = 0
UNION
SELECT a.id
FROM tbl_money a
WHERE a.amount = 14
AND a.used = 1
AND MOD(a.amount, 2) = 0
这是我的 mysql table.
CREATE TABLE IF NOT EXISTS tbl_money (
id int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
amount int(11) NOT NULL,
used int(11) NOT NULL
) ENGINE=InnoDB AUTO_INCREMENT=15 DEFAULT CHARSET=latin1;
INSERT INTO tbl_money ( id , amount , used ) VALUES
(8, 2, 0),
(9, 4, 0),
(10, 4, 0),
(11, 3, 0),
(12, 8, 0),
(13, 10, 0),
(14, 13, 0);
Id 是一个主键字段,money 可以是从 1 到任意数字的任意数字。
问题: 假设我必须从数量为 8 的 table 中找到 id。这很简单,因为 id 5 包含数量 8。但是如果我必须找到数量为 14 的不存在的 id。我现在必须 select 2 个或更多字段,总和等于 14。例如在上面 table 我可以 select id 6 和 id 3 总和等于 14。就像我需要找到 6 我必须 select id 1 和 2 因为它们的总和等于 6。
有时我们可能需要 select 超过 2 行才能使总和相等。但是如果任何条件不匹配 table 的所有行,我们可以 return 0.
条件: 已被占用的行不能再次 selected。使用的字段应始终为 0。如果使用的字段值为 1,我们不能 select 它。我们只会搜索偶数,所以我们不需要担心奇数。
请建议我如何解决这个算法。提前致谢。
以下只是一个想法,尝试在函数或SP中实现它。
想法一:
我。判断得到的值是ODD还是EVEN。
二。如果是偶数,则尝试在您的帐户中添加 两个偶数 号码或 两个奇数 号码 table 并检查它是否符合您的值。
三。如果是奇数,则尝试从 table 中添加 一个偶数 号码和 一个奇数 号码并检查它是否与您的值匹配。
四。如果你没有得到结果,那么
- 如果是偶数,加三个偶数个数
- 如果是奇数,添加三个奇数 号码或两个偶数 号码和一个奇数 号码
思路二:(这会很简单)
我。从样本数据中取 first 值,取值 2
并添加其他行值,例如 2+4 == 14, 2+4 == 14, 2+3 == 14, 2+8 == 14, 2+10 == 14, 2+13 == 14
二。然后取 第二行值 说值 4
并添加其他值,如 4+4 == 14, 4+3 == 14, 4+8 == 14, 4+10== 14, 4+13 == 14
。这里 4+10
匹配值 14
。 (如果您需要所有组合,则继续执行,否则中断此执行)。
三。一旦 10+13
组合完成,然后添加前两个值并添加其他值,例如 6+4, 6+3, 6+8, 6+10, 6+13
四。继续直到组合 31(2+4+4+3+8+10)+13
希望对您有所帮助。
纯粹的 SQL 方法,可能效率不高:-
SELECT CONCAT_WS(',', a.id, b.id, c.id, d.id)
FROM tbl_money a
INNER JOIN tbl_money b ON b.id > a.id
INNER JOIN tbl_money c ON c.id > b.id
INNER JOIN tbl_money d ON d.id > c.id
WHERE a.amount + b.amount + c.amount + d.amount = 14
UNION
SELECT CONCAT_WS(',', a.id, b.id, c.id)
FROM tbl_money a
INNER JOIN tbl_money b ON b.id > a.id
INNER JOIN tbl_money c ON c.id > b.id
WHERE a.amount + b.amount + c.amount = 14
UNION
SELECT CONCAT_WS(',', a.id, b.id)
FROM tbl_money a
INNER JOIN tbl_money b ON b.id > a.id
WHERE a.amount + b.amount = 14
UNION
SELECT a.id
FROM tbl_money a
WHERE a.amount = 14
编辑 - 修改以检查使用的字段,并且金额不是奇数
SELECT CONCAT_WS(',', a.id, b.id, c.id, d.id)
FROM tbl_money a
INNER JOIN tbl_money b ON b.id > a.id AND b.used = 1 AND MOD(b.amount, 2) = 0
INNER JOIN tbl_money c ON c.id > b.id AND c.used = 1 AND MOD(c.amount, 2) = 0
INNER JOIN tbl_money d ON d.id > c.id AND d.used = 1 AND MOD(d.amount, 2) = 0
WHERE a.amount + b.amount + c.amount + d.amount = 14
AND a.used = 1
AND MOD(a.amount, 2) = 0
UNION
SELECT CONCAT_WS(',', a.id, b.id, c.id)
FROM tbl_money a
INNER JOIN tbl_money b ON b.id > a.id AND b.used = 1 AND MOD(b.amount, 2) = 0
INNER JOIN tbl_money c ON c.id > b.id AND c.used = 1 AND MOD(c.amount, 2) = 0
WHERE a.amount + b.amount + c.amount = 14
AND a.used = 1
AND MOD(a.amount, 2) = 0
UNION
SELECT CONCAT_WS(',', a.id, b.id)
FROM tbl_money a
INNER JOIN tbl_money b ON b.id > a.id AND b.used = 1 AND MOD(b.amount, 2) = 0
WHERE a.amount + b.amount = 14
AND a.used = 1
AND MOD(a.amount, 2) = 0
UNION
SELECT a.id
FROM tbl_money a
WHERE a.amount = 14
AND a.used = 1
AND MOD(a.amount, 2) = 0