我们有一个包含网站的页面访问量,像一个表: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