[英]Merging multiple rows according to an order
假設有以下幾行
| 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 | |
我們要根據以下優先級合並這些行:
已停止>正在運行>就緒>(空或空)
如果某行具有最高優先級的值,則應使用該行中的值(僅當它不為null時)。 如果為null,則應使用任何其他行中的值。 行應按ID分組
上述輸入的正確輸出是:
| Id | MachineName | WorkerName | MachineState |
|----------------------------------------------|
| 1 | Beta | Foo | STOPPED |
| 2 | Yuu | Jaam | STOPPED |
| 3 | Iem | Fish | RUNNING |
什么是一個很好的SQL查詢來做到這一點? 我嘗試使用聯接,但沒有成功。
這是一個優先級查詢。 一種方法使用變量。 另一個union all
使用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'));
您可以將其視為逐組最大問題的一種情況,前提是您可以在MachineState
列上獲得適當的排序,例如使用CASE
表達式:
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
在sqlfiddle上看到它:
| id | machinename | workername | machinestate | |----|-------------|------------|--------------| | 1 | Beta | Foo | STOPPED | | 2 | Yuu | Jaam | STOPPED | | 3 | Iem | Fish | RUNNING |
如果MachineState
是ENUM
類型的列(以適當的順序定義),則MachineState
使用CASE
MachineState
。 在這種情況下,對字符串值進行簡單的字典排序將產生相同的結果,但這是一個巧合,您確實不應該依賴於此,因為當有人嘗試將其保留在代碼中時,它必然會在雷達下溜走。未來。
將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;
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.