2013-10-28 73 views
1

我試圖分解並重新編寫由已離開的開發人員創建的視圖。該查詢需要三個以上的minuites訪問,我從所有的CONCATs假設。SQL VIEW簡化/解決方案更快Querys

CREATE VIEW `active_users_over_time` AS 
select 
    `users_activity`.`date` AS `date`, 
    time_format(
     addtime( 
      concat(`users_activity`.`date`,' ',`users_activity`.`time`), 
      concat('0 ',sec_to_time(`users_activity`.`duration_checkout`),'.0') 
     ),'%H:%i:%s') AS `time`, 
    `users_activity`.`username` AS `username`, 
    count(addtime(concat(`users_activity`.`date`,' ',`users_activity`.`time`), 
    concat('0 ',sec_to_time(`users_activity`.`duration_checkout`),'.0'))) AS `checkouts` 
from `users_activity` 
group by 
    concat(
     addtime(
      concat(`users_activity`.`date`,' ',`users_activity`.`time`), 
      concat('0 ',sec_to_time(`users_activity`.`duration_checkout`),'.0') 
     ), 
     `users_activity`.`username`); 

的數據來自SQL表:

CREATE TABLE `users_activity` (
    `id` int(10) unsigned NOT NULL auto_increment, 
    `featureid` smallint(5) unsigned NOT NULL, 
    `date` date NOT NULL, 
    `time` time NOT NULL, 
    `duration_checkout` int unsigned NOT NULL, 
    `update_date` date NOT NULL, 
    `username` varchar(255) NOT NULL, 
    `checkout` smallint(5) unsigned NOT NULL, 
    `licid` smallint(5) unsigned NOT NULL, 
    PRIMARY KEY (`id`), 
    UNIQUE KEY `featureid_licid_username` (`featureid`,`licid`,`date`,`time`,`username`), 
    FOREIGN KEY(featureid) REFERENCES features(id) 
) ENGINE=MyISAM DEFAULT CHARSET=latin1; 

我有一個很難decifering正是心不是需要什麼需要什麼和什麼。

任何人有任何想法?謝謝。

+0

它來自一張表嗎?你可以從視圖中運行選擇,看看它是如何執行的?並將其與查詢的簡化版本(沒有所有連接等)進行比較。 – Andrew

+0

我不知道mysql是否具有此功能,但是我會爲您在sql server中連接的內容創建持久性計算列。然後,您只需在輸入或更改數據時進行計算,而不是每次需要獲取數據。 – HLGEM

+0

沒有什麼看起來真的太重了。如果您運行查詢,視圖正在執行,是否需要運行相同的三分鐘?我幾乎要回到需要......他究竟想用那麼大的time_formt來顯示(線? – Twelfth

回答

2

我認爲這確實是原來的查詢做的一切,跳過一堆多餘的步驟:

select `date` 
, `time` 
, `username` 
, count(1) as `checkouts` 
from 
(
    select 
    `users_activity`.`date` AS `date` 
    ,time_format(
    addtime(`users_activity`.`date`,`users_activity`.`time`) 
    + interval `users_activity`.`duration_checkout` second 
    ,'%H:%i:%s' 
    ) AS `time` 
    ,`users_activity`.`username` AS `username` 
    from `users_activity` 
) x 
group by `username`, `date`, `time` 

您可能也想看看在桌子上什麼索引,看的優化,可以在其他地方做(例如,如果你還沒有用戶名和日期字段的索引,你可以通過添加一個來獲得這個查詢的很多好處)。

+1

這看起來像是在詭計!謝謝!清潔的格式也使我更容易說出它應該做什麼,我欠你一個 – TrinaryOC

-2

你可以從這個重寫GROUP BY化酶啓動:

group by 
    concat(
     addtime(
      concat(`users_activity`.`date`,' ',`users_activity`.`time`), 
      concat('0 ',sec_to_time(`users_activity`.`duration_checkout`),'.0') 
     ), 
     `users_activity`.`username`); 

這一個:

GROUP BY `users_activity`.`date`, 
     `users_activity`.`time`, 
     `users_activity`.`duration_checkout`, 
     `users_activity`.`username` 

這種變化應該給於轉換日期字符串和連接他們產生了一些積蓄,
並且查詢的結果不應該改變。

然後,您可以考慮在GROUP BY列上創建組合索引。
根據此鏈接:http://dev.mysql.com/doc/refman/5.0/en/group-by-optimization.html

使用索引GROUP BY最重要的前提條件是所有GROUP BY列來自同一指數

這意味着引用屬性,如果我們創建以下索引:

CREATE INDEX idx_name ON `users_activity`(
    `date`,`time`,`duration_checkout`,`username` 
); 

然後MySql可能會使用它來優化GROUP BY(但存在沒有保證)。

+1

注意:因爲時間和持續時間是在原始文件中加在一起的,所以這個小組的行爲有點不同;即'10:00:00 + 60'與'10:01:00 + 0'相同;所以在原來的那些將被分組,而在這個版本中,他們不是。 – JohnLBevan