我們有一個包含網站的頁面訪問量,像一個表:MySQL:用FROM子句中的相關子查詢重寫MSSQL?
time | page_id
----------|-----------------------------
1256645862| pageA
1256645889| pageB
1256647199| pageA
1256647198| pageA
1256647300| pageB
1257863235| pageA
1257863236| pageC
在我們的生產表,目前大約40K行。我們要生成,每天的獨特網頁在過去30天裏瀏覽,60天,90天計數。因此,在結果集中,我們可以查找了一天,看到獨特頁是多少那一天之前的60天期限內訪問。
我們能夠得到一個查詢的MSSQL工作:
SELECT DISTINCT
CONVERT(VARCHAR,P.NDATE,101) AS 'DATE',
(SELECT COUNT(DISTINCT SUB.PAGE_ID) FROM (SELECT PAGE_ID FROM perflog WHERE NDATE BETWEEN DATEADD(D,-29,P.NDATE) AND P.NDATE) AS SUB) AS '30D',
(SELECT COUNT(DISTINCT SUB.PAGE_ID) FROM (SELECT PAGE_ID FROM perflog WHERE NDATE BETWEEN DATEADD(D,-59,P.NDATE) AND P.NDATE) AS SUB) AS '60D',
(SELECT COUNT(DISTINCT SUB.PAGE_ID) FROM (SELECT PAGE_ID FROM perflog WHERE NDATE BETWEEN DATEADD(D,-89,P.NDATE) AND P.NDATE) AS SUB) AS '90D'
FROM PERFLOG P
ORDER BY 'DATE'
注:由於MSSQL不具備FROM_UNIXTIME功能,我們增加了測試NDATE列,它僅僅是轉換time
。生產表中不存在NDATE。
這個查詢轉換到MySQL爲我們提供了「未知科拉姆P.time」錯誤:
SELECT DISTINCT
FROM_UNIXTIME(P.time,'%Y-%m-%d') AS 'DATE',
(SELECT COUNT(DISTINCT SUB.PAGE_ID) FROM (SELECT PAGE_ID FROM perflog WHERE FROM_UNIXTIME(time,'%Y-%m-%d') BETWEEN DATE_SUB(FROM_UNIXTIME(P.time,'%Y-%m-%d'), INTERVAL 30 DAY) AND FROM_UNIXTIME(P.time,'%Y-%m-%d')) AS SUB) AS '30D',
(SELECT COUNT(DISTINCT SUB.PAGE_ID) FROM (SELECT PAGE_ID FROM perflog WHERE FROM_UNIXTIME(time,'%Y-%m-%d') BETWEEN DATE_SUB(FROM_UNIXTIME(P.time,'%Y-%m-%d'), INTERVAL 60 DAY) AND FROM_UNIXTIME(P.time,'%Y-%m-%d')) AS SUB) AS '60D',
(SELECT COUNT(DISTINCT SUB.PAGE_ID) FROM (SELECT PAGE_ID FROM perflog WHERE FROM_UNIXTIME(time,'%Y-%m-%d') BETWEEN DATE_SUB(FROM_UNIXTIME(P.time,'%Y-%m-%d'), INTERVAL 90 DAY) AND FROM_UNIXTIME(P.time,'%Y-%m-%d')) AS SUB) AS '90D'
FROM PERFLOG P
ORDER BY 'DATE'
我明白這是因爲我們不能有一個相關子查詢,在外部FROM子句引用的表。但是,不幸的是,我們在如何將這個查詢轉換爲在MySQL中工作時遇到了困難。現在,我們只需返回表中的所有DISTINCT行,並在PHP中進行後處理。 40K行花費大約2-3秒。當我們有100個1000行的行時,我擔心這個表現。
是否有可能在MySQL中嗎?如果是這樣,我們可以期望它比我們的PHP後處理解決方案表現更好。
UPDATE: 這裏的查詢創建表:
CREATE TABLE `perflog` (
`user_id` VARBINARY(40) NOT NULL ,
`elapsed` float UNSIGNED NOT NULL ,
`page_id` VARCHAR(255) NOT NULL ,
`time` INT(10) UNSIGNED NOT NULL ,
`ip` VARBINARY(40) NOT NULL ,
`agent` VARCHAR(255) NOT NULL ,
PRIMARY KEY ( `user_id` , `page_id` , `time` , `ip`, `agent`)
) ENGINE MyISAM
我司生產的表有40K〜行迄今!
您可能想要發佈用於創建perflog表的DDL。請包括您添加到其中的任何索引。 – mooreds 2009-11-20 21:12:08