簡體   English   中英

根據訂單合並多行

[英]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 |

如果MachineStateENUM類型的列(以適當的順序定義),則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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM