假设有以下行
| Id | MachineName | WorkerName | MachineState |
|----------------------------------------------|
| 1 | Alpha | Young | RUNNING |
| 1 | Beta | | STOPPED |
| 1 | Gamma | Foo | READY |
| 1 | Zeta | Zatta | |
| 2 | Guu | Niim | RUNNING |
| 2 | Yuu | Jaam | STOPPED |
| 2 | Nuu | | READY |
| 2 | Faah | Siim | |
| 3 | Iem | | RUNNING |
| 3 | Nyt | Fish | READY |
| 3 | Qwe | Siim | |
我们希望根据以下优先级合并这些行:
STOPPED>跑步>准备> (null或空)
如果某行具有最高优先级的值,则应使用该行的值(仅当该行不为空时)。如果为null,则应使用来自任何其他行的值。行应按id
分组上述输入的正确输出为:
| Id | MachineName | WorkerName | MachineState |
|----------------------------------------------|
| 1 | Beta | Foo | STOPPED |
| 2 | Yuu | Jaam | STOPPED |
| 3 | Iem | Fish | RUNNING |
什么是一个很好的SQL查询来完成这个?我尝试使用连接,但它没有用完。
答案 0 :(得分:1)
这是优先级查询。一种方法使用变量。另一个使用union all
。 。 。如果对于给定的id不重复状态,则此方法有效:
select t.*
from table t
where machinestate = 'STOPPED'
union all
select t.*
from table t
where machinestate = 'RUNNING' and
not exists (select 1 from table t2 where t2.id = t.id and t2.machinestate in ('STOPPED'))
union all
select t.*
from table t
where machinestate = 'READY' and
not exists (select 1 from table t2 where t2.id = t.id and t2.machinestate in ('STOPPED', 'RUNNING'));
答案 1 :(得分:1)
如果您可以通过>>> from itertools import takewhile
>>> input = '123abc456def'
>>> ''.join(takewhile(str.isdigit, input))
'123'
列获得合适的排序,则可以将此视为分组最大问题的一种情况。使用CASE
表达式:
MachineState
在sqlfiddle上看到它:
| id | machinename | workername | machinestate | |----|-------------|------------|--------------| | 1 | Beta | Foo | STOPPED | | 2 | Yuu | Jaam | STOPPED | | 3 | Iem | Fish | RUNNING |
如果SELECT a.Id,
COALESCE(a.MachineName, t.MachineName) MachineName,
COALESCE(a.WorkerName , t.WorkerName ) WorkerName,
a.MachineState
FROM myTable a JOIN (
SELECT Id,
MIN(MachineName) AS MachineName,
MIN(WorkerName ) AS WorkerName,
MAX(CASE MachineState
WHEN 'READY' THEN 1
WHEN 'RUNNING' THEN 2
WHEN 'STOPPED' THEN 3
END) AS MachineState
FROM myTable
GROUP BY Id
) t ON t.Id = a.Id AND t.MachineState = CASE a.MachineState
WHEN 'READY' THEN 1
WHEN 'RUNNING' THEN 2
WHEN 'STOPPED' THEN 3
END
是ENUM
类型列(按适当的顺序定义),您可以省去使用CASE
的痛苦。在这种情况下会发生这样的情况:对字符串值进行简单的字典排序会产生相同的结果,但这是你不应该依赖的巧合,因为它必然会在雷达下滑动当有人试图在将来维护此代码时。
答案 2 :(得分:0)
将MachineState更改为枚举:
`MachineState` enum('READY','RUNNING','STOPPED') DEFAULT NULL
和sql很简单:
select t.id,state.machinename,state.workername,t.mstate from state,(select id,max(MachineState) mstate from state group by Id) t where t.mstate=state.machinestate and t.id=state.id;