使用两个表,一对多关系,我需要更新所有子条目的最强状态的父表。根据表2中的条目,Table1的结果应如下所示:
+-----------------------+ +-----------------------+
| Table1 | | Table2 |
+-----------------------+ +-----------------------+
| table1_id |status1 | | table1_id |status2 |
+-----------------------+ +-----------------------+
|0 |1 | |0 |1 |
|1 |0 | |0 |1 |
|2 |2 | |1 |0 |
|3 |0 | |1 |2 |
+-----------------------+ |2 |1 |
|2 |2 |
|3 |1 |
|3 |0 |
+-----------------------+
0表示最强,1表示最弱,2表示中等。
我考虑过使用MIN()
或MAX()
,或者甚至将每个父项的所有子条目相乘,并将2用于任何大于2的项,但是保留0或1。 MySQL的这个有点超出了我的想法。
答案 0 :(得分:1)
如果0-1-2是订单会更简单,因为你可以使用单个min()函数。这样你需要在内部稍微调整min()函数以给予数字1不同的权重,你需要用另一个case表达式来解释设置部分中的结果:
update table1,
(select table1_id, min(case status2 when 1 then 3 else status2 end) as status2
from table2
group by table1_id) t2
set table1.status1=case t2.status2 when 3 then 1 else status2 end
where table1.table1_id=t2.table1_id
答案 1 :(得分:1)
select t.table1_id, (max((t.status2 + 2) mod 3) + 1) mod 3 as status1
from Table2 t
group by t.table1_id
http://sqlfiddle.com/#!9/8b293/8
说明:
我们需要一个函数 f(n),它将把数字(0,1,2)转换成之间 f(2)的排序方式f(0)和 f(1)。有几种方法可以实现这一目标。例如 f(n)= abs(n - 1.1)将转换:
0 -> 1.1
1 -> 0.1
2 -> 0.9
如果我们只需要订购结果,这就行了。
create table t (n int);
insert into t values (0), (1), (2);
select n, abs(n - 1.1)
from t
order by abs(n - 1.1) desc;
--
n abs(n - 1.1)
0 1,1
2 0,9
1 0,1
但是如果我们想在没有子查询的MAX
语句中使用MIN
或GROUP BY
,则该函数必须是可逆的。所以我们还需要一个函数 g(m),其中 g(f(n))= n 。因为我们只有3个值,所以我们可以使用模数函数“旋转”数字,直到我们得到所需的顺序。
select n
, (n + 1) mod 3 as rotate_1
, (n + 2) mod 3 as rotate_2
, (n + 3) mod 3 as rotate_3
from t
--
n rotate_1 rotate_2 rotate_3
0 1 2 0
1 2 0 1
2 0 1 2
我们看到, f(n)=(n + 2)mod 3 (rotate_2)是我们需要的功能。我们可以在该函数上使用MAX
。要将其转换回原始数字,我们只需要再次使用 g(m)=(m + 1)mod 3 “旋转”。 “最强”的数字是 g(MAX(f(n)))
select
(MAX((n + 2) mod 3) + 1) mod 3 as strongest,
(MIN((n + 2) mod 3) + 1) mod 3 as weakest
from t
--
strongest weakest
0 1
可以在GROUP BY
语句中使用它来获得每个项目的“最强”数字。