2016-08-02 52 views
1

我有兩個表(事件和發生次數)。每個事件在事件表中有0個或多個條目。我想總結事件的數量並獲得前5個結果。只要所有事件在發生表中都有條目,我就有一些適用於此的SQL。發生表中沒有條目的事件發生在列表頂部。如何選擇3個最大的結果,但排除空值

什麼是正確的SQL來實現這一目標?

表定義

事件
ID - 整數
事件名稱 - VARCHAR(200)

紀錄
ID - INT
EVENT_ID - INT
時間戳 - 日期時間
TimesOccurred - int

ID爲1的事件(事件名稱 - '上下文切換'),我可能會在出現表中相應的行:

ID:1,EVENT_ID:1,時間戳:「2016- 08-02五點52分00' 秒,TimesOccurred:50
ID:8,EVENT_ID:1,時間戳: '2016年8月2日七時11分00秒',TimesOccurred:20

我將不得不在發生表中有相應條目的其他事件,以及沒有相應條目的事件(尚未發生,偶發事件等)

以下SQL將通過爲具有相同ID的所有事件合計TimesOccurred列,爲我提供前5個發生的事件。

SELECT Events.Name, t.total as Total FROM Events 
LEFT JOIN 
(SELECT Occurrences.Event_ID, sum(Events.TimesOccurred) as total FROM Occurrences 
INNER JOIN Events on Events.id = Occurrents.Event_ID GROUP BY Events.id) t 
on Events.id = t.Event_ID ORDER BY t.total DESC limit 5; 

這可能給我

段錯誤20
上下文切換10

但是,如果我有一個名爲OOM與3的ID的事件,並沒有條目在Event_ID爲3的Occurrences表中,我會得到以下內容

OOM
段錯誤20
上下文切換10

我試圖改變我的查詢:

SELECT Events.Name, COALESCE(t.total, 0) as Total FROM Events 
LEFT JOIN 
(SELECT Occurrences.Event_ID, sum(Events.TimesOccurred) as total FROM Occurrences 
INNER JOIN Events on Events.id = Occurrents.Event_ID GROUP BY Events.id) t 
on Events.id = t.Event_ID ORDER BY t.total DESC limit 5; 

這則返回

OOM 0
段錯誤20
上下文切換10

我相信這是因爲我在t.total上進行排序,並且COALESC沒有將t.total設置爲0,而結果爲null,而是在結果爲null的情況下返回0。

任何想法如何從我排名前5的事件中排除空值?

感謝,

+1

'sum(Events.TimesOccurred)'????? TimesOccurred Occurrences表的權利? – jonju

回答

3

在Postgres裏,你可以通過排序方向後加入NULLS [LAST/FIRST]ORDER BY條款定義空值的處理。

此外,您只需要訪問兩個表一次 - 額外的派生表是沒有必要的。

SELECT Events.Name, sum(Occurences.TimesOccurred) as Total 
FROM Events 
LEFT JOIN Occurrences ON Events.id = Occurrences.Event_ID 
GROUP BY 1 
ORDER BY 2 DESC NULLS LAST 
LIMIT 5 

manual大膽重點煤礦 - 你在你的前5名的查詢都拿到空的原因):

默認情況下,空值排序彷彿比任何非空值時; 即NULLS FIRST是DESC訂單和NULLS LAST 的默認值。

如果您仍然需要返回0時,有沒有occurencies(因爲你可能有5個或更少的事件總數),然後添加COALESCE()是要走的路 - 這你做的方式。


我還添加整數別名列GROUP BYORDER BY條款。

您也可以爲您的表名縮短代碼的別名。

1

我建議你簡化查詢和使用NULLS LAST

SELECT e.Name, sum(o.TimesOccurred) as total 
    FROM Events e LEFT JOIN 
     Occurrences o I 
     ON Events.id = o.Event_ID 
    GROUP BY e.Name 
    ORDER BY total DESC NULLS LAST 
    LIMIT 5; 

注意,只有一兩個表需要之間的連接。