2017-04-18 50 views
0

假設我們有這些表,指一個任務單個客戶SQL:如何根據日期取一個獨特的記錄(用NULL情況包括在內)

AGENDAS 
ID | DAY 
86 | 2017-04-14 
88 | 2017-04-22 

WORKS 
ID     | IDAGENDA | TIME SLOT | RESULT | DATETIMEEXECUTED | IDORDER 
IZ9`fiq|-=rRE7OKKO;P | 86 | 8-10 am | canceled | 2017-04-13 10:45 | 10 
g5wMkHa4Z?bQnFqDmXKn | 88 | 8-10 am | canceled | 2017-04-19 16:30 | 10 
n\mkLegfO>HSCJ/X:{ax | 88 | 13-15 pm |   |     | 10 

與框架做我(我不得不)使用,當我創建一個面板時,我被允許編寫一個查詢以獲取其數據。該查詢稱爲主查詢。 我的老闆想要一個總結屏幕,對於每個工作訂單,我必須列出最新的議程,以及案例的結果。所以,假設我們有上述表格的情況。在這種情況下,我應該只列出ID爲n\mkLegfO>HSCJ/X:{ax的任務,因爲它是最近插入和保留的任務,並且仍然需要執行(客戶沒有取消它)。 但我不知道,因爲如果如何獲取這個唯一的記錄,在主查詢,我寫:

select ... 
from ORDERS O left join AGENDAS A on ... 
    left join WORKS W1 on ... 
where W1.IDORDER = 10 and W1.DATETIMEEXECUTED = (
    select max(W2.DATETIMEEXECUTED) 
    from WORKS W2 
    where W2.IDORDER = 10 
) 

則記錄

g5wMkHa4Z?bQnFqDmXKn | 88 | 8-10 am | canceled | 2017-04-19 16:30 

將返回這是不是最近。在另一方面,如果我嘗試:

select ... 
from ORDERS O left join AGENDAS A on ... 
    left join WORKS W1 on ... 
where W1.IDORDER = 10 and (DATETIMEEXECUTED is null or W1.DATETIMEEXECUTED = (
    select max(W2.DATETIMEEXECUTED) 
    from WORKS W2 
    where W2.IDORDER = 10) 

然後我得到:

g5wMkHa4Z?bQnFqDmXKn | 88 | 8-10 am | canceled | 2017-04-19 16:30 | 10 
n\mkLegfO>HSCJ/X:{ax | 88 | 13-15 pm |   |     | 10 

仍然是不正確的。 我認爲最大的問題是,我不能因爲被現場工作人員在移動設備中創建這些記錄時,PK不能是簡單的整數計數器和每個設備移動作爲的SQLite上WORKS表執行max(ID)聚合函數和每個操作員創建他將自己的記錄與中央服務器同步之前。這就是爲什麼我們的框架提供了一個PK作爲char(20)僞隨機字符。

因爲我是個白癡,我沒想到創建工作的日期時間,但這個應用程序已經在生產,所以我不希望改變DB模式。 此外left join是必需的,因爲對於其他人,仍然沒有議程和任命可能仍然存在。

那麼,到底:如果只有caneled作品我想看看最近的一次。相反,如果還有一項工作仍在進行(結果和日期時間等於null),我希望得到它。 有沒有解決方案?

+0

它是sql服務器...因爲我添加了 –

+0

您是否正在尋找* one * IDORDER(例如IDORDER = 10)或* multiple * IDORDER及其最新記錄的最新記錄? –

+0

AGENDAS表格與此有什麼關係? –

回答

2

爲idorder的最新記錄= 10:

select top(1) * 
from works 
where idorder = 10 
    and coalesce(result, 'okay') <> 'canceled' 
order by datetimeexecuted desc; 

每idorder的最新記錄:

select * 
from 
(
    select *, row_number() over (partition by idorder order by datetimeexecuted desc) as rn 
    from works 
    where coalesce(result, 'okay') <> 'canceled' 
) ranked 
where rn = 1; 

更新:每idorder最新未取消的記錄,如果有,否則最新的其他記錄:

select * 
from 
(
    select *, 
    row_number() over (partition by idorder order by 
     case when result = 'canceled' then 2 else 1 end, datetimeexecuted desc) as rn 
    from works 
) ranked 
where rn = 1; 
+0

Ehm,這個查詢應該在服務器上運行,所以我不能使用coalesce –

+1

我不明白這一點。 'COALESCE'是標準的SQL,可在SQL Server中使用。爲什麼你會被允許運行查詢,但只有沒有'COALESCE'?這似乎沒有道理。 (無論如何,'coalesce(result,'okay')<>'cancelled''也可以寫成'result''''取消'或結果爲空'。) –

+0

對不起。我只在SQLite中看到'COALESCE()',而在SQL Server中看到'ISNULL()'等其他例程。實現該框架的同一位人員向我解釋說,合併是保留給SQLite的。抱歉。無論如何,恐怕我不允許插入一個SELECT查詢作爲參數到FROM但只有表。我知道這個框架是有限的...... –

0

UPDATE

正如他在很好的答案建議由和Thorsten KETTNER,我創建了一個新的標準視圖,其查詢是完全內SELECT *, row_number()...,我用的面板,而不是的WORKS經典表的主查詢這一觀點。 最後,是我的情況更準確,我必須執行以下操作:

select ... 
from ORDERS O left join AGENDAS A on ... 
       left join VIEW V on ... 
where V.rn = 1 or (V.rn is null) 

,因爲如果工作/任命尚未仍然在所有插入的,他們希望看到的其他有關資料無論如何。

相關問題