2014-01-10 48 views
0

那麼這不是一個非常明確的標題,是嗎?SQLite:爲列中的每個不同值找到前n個聚合

我有一個SQLite表results

event | dayOfWeek | hour| eventCount 
--------+-----------+-----+------------ 
Event A | 0   | 0 | 4926 
Event A | 0   | 1 | 1492 
... 
Event A | 1   | 0 | 7372 
Event A | 1   | 1 | 49 
... 
Event B | 0   | 0 | 234648 
... 

它只包含的時間每個事件發生在一週的每一天的每一個小時數。

我一直在建立一個表daily這樣的:

create table daily as 
select event, 
     sum(case when dayOfWeek = 0 then count else 0 end) as sunday, 
     sum(case when dayOfWeek = 1 then count else 0 end) as monday, 
     sum(case when dayOfWeek = 2 then count else 0 end) as tuesday, 
     sum(case when dayOfWeek = 3 then count else 0 end) as wednesday, 
     sum(case when dayOfWeek = 4 then count else 0 end) as thursday, 
     sum(case when dayOfWeek = 5 then count else 0 end) as friday, 
     sum(case when dayOfWeek = 6 then count else 0 end) as saturday 
from results 
group by event; 

爲了得到一個表,看起來像這樣:

event |sunday|monday|tuesday|wednesday|thursday|friday|saturday 
--------+------+------+-------+---------+--------+------+--------- 
Event A | 345 | 2345 | 341 | 568  | 689 | 2351 | 1455 
... 

其中只包含計數爲每個事件類型中的每一天星期。在一天中的每小時和每天/每小時建立一個類似的表是微不足道的,並且我有兩個表可用。

我想提出一個表topTenPerHour這樣的:

hour | 1st  | 2nd  | 3rd  | ... 
-----+---------+---------+---------+------ 
0 | Event A | Event C | Event B | ... 
1 | Event B | Event D | Event C | ... 
... 
23 | Event A | Event R | Event D | ... 

但我無法看到如何。有什麼建議麼?編輯:我實際上並不需要創建一個表(我只需要做一個SELECT調用),所以SQLite對CREATE TABLE的限制(如JOIN的不可用性)不適用於此問題。

回答

0

您已經在這裏以過於複雜的方式設置您的數據庫。

你應該有:

  • 的事件類型表定義每個事件
  • 的事件日誌表,登記每個人的事件,用「EventTypeId」外鍵和時間戳。

然後您可以在查詢中使用數據庫函數來執行其他任何操作。嘗試將所有這些信息存儲在表中是多餘的,因爲它已經固有地存在於其他表中。應該是訪問數據庫的程序的工作,以調用正確的查詢而不是數據庫的作業來保存冗餘信息。

如果您對靜態數據進行相同的查詢(因爲它很少更新),那麼按照您現在設置的方式執行此操作通常只是一個好主意。在這種情況下,只會因爲擔心優化查詢的運行時而使用它。

+0

感謝您的建議,@Alexander!我實際上正在處理完全靜態的歷史數據。我也只創建一個有問題的表格用於報告。數據庫將不會在項目完成後維護。實際上,我將數據存儲在與您的建議非常相似的佈局中。我只是爲演示和分析而創建中間表。這是一個非常大的數據庫,並且擁有這些中間表可極大地減少我的查詢的運行時間。對於如何使用當前佈局製作表格,您有什麼建議嗎? –

0

正如您在其他查詢中看到的,SQL的設計並非真正具有多個具有相似含義的列;你最終會複製很多代碼。

對於頂部ñ值,我們需要計算自己的排名,在這種情況下是不哈瓦較小的事件計數爲同一小時的記錄數:

CREATE VIEW /* or TABLE */ ranks AS 
SELECT hour, 
     event, 
     (SELECT COUNT(*) 
     FROM results 
     WHERE hour = hours.hour 
      AND eventCount >= hours.eventCount 
     ) AS rank 
FROM (SELECT DISTINCT event, 
         hour 
     FROM results) AS hours 

然後我們從每列的特定等級的記錄中取值:

SELECT hour, 
     (SELECT event FROM ranks WHERE hour = h.hour AND rank = 1) AS "1st", 
     (SELECT event FROM ranks WHERE hour = h.hour AND rank = 2) AS "2nd", 
     ... 
FROM (SELECT DISTINCT hour 
     FROM results) AS h 
ORDER BY hour