2013-08-02 93 views
0

我有一個表,看起來是這樣的:轉換表的最佳方式是什麼?

users_data_points:

id | users_id | data_types_id | value | events_id | time_inserted 

data_type_id地圖,如「名」或「地址」或一千其他數據類型的一些任意的事情。

所以,對任何個人用戶,我可以在這個表中的行N多。

有成千上萬這些行。

從該表中直接基於event_id的選擇是非常快,併產生項的長列表,其中每個用戶由一些數量的行,每個都包含一個單獨的數據點來表示。

但是,當我需要在INDIVIDUAL行中獲取每個用戶和他們數據的一些子集的結果時,我通常會使用子查詢,現在這個過程會磨合到冰河的步伐。

我的查詢一下(約)是這樣的:

select users_id as uid, 
events_id as eid, 
(select `value` from users_data_points where users_id = uid and events_id = eid and data_type_id = 3 limit 1) as 'firstName, 
     -- ... however many more of these subselects I need here 
     from users_data_points where events_id = 500 and date(time_inserted) between '2013-01-01' and date(now()) 

我對能以更有效的方式產生這種結果的任何替代解決方案完全開放。在生產中,我實際上只是抓住原始行,然後在Node中將它們散列在一起。這是一個數量級比SQL的子查詢更快,但我更喜歡以這種方式不分裂的工作,如果有一個更好的方式來利用MySQL來執行這項任務。

我完全開放臨時表或視圖或派生表或任何其他可能工作,但我試過的一切實際上移動甚至比上述解決方案更慢。

+1

我絕對建議找到擺動表的替代方案;在MySQL中做這件事並不是很有趣。 –

回答

0

我完全贊同G-掘金的評論。數據庫是不是有格式的數據很好,但是,只是爲了它的緣故,你可以做

select users_id as uid, 
events_id as eid, 
max(case when data_type = 3 then `value` end) as first_name, 
... 
from users_data_points 
where events_id = 500 
and date(time_inserted) between '2013-01-01' and date(now()) 
group by users_id 

如果選擇MIN()或MAX()作爲聚合函數沒有關係。隨着case...when S(不含GROUP BY和聚合函數)你喜歡的東西

user_id | first_name | last_name | ... 
1    john    null   null 
1    null    jack   null 
1    null    null   whatever 

與本集團,你會得到它在一條線上的聚合函數,瞧,你有你的支點沒有子查詢。這應該比你現在運行的要快多倍,你仍然可以在應用層上獲得更高的性能。

相關問題