我们有一个统计数据库,我们希望将一些结果分组。每个条目都有一个时间戳'tstarted'。
我们希望在每天的每个季度进行分组。对于每个季度,我们想知道我们所拥有的日期数> 0结果(该季度)。
我们可以使用子查询来解决这个问题:
select quarter, sum(q), count(quarter), sum(q) / count(quarter) as average
from (
select SEC_TO_TIME((TIME_TO_SEC(tstarted) DIV 900) * 900) as quarter, sum(qdelivered) as q
from statistics
where stat_field = 1
group by SEC_TO_TIME((TIME_TO_SEC(tstarted) DIV 900) * 900), date(tstarted)
order by SEC_TO_TIME((TIME_TO_SEC(tstarted) DIV 900) * 900) asc
) as sub
group by quarter
我的问题:是否有更有效的方法来检索此结果(例如加入或其他方式)?
答案 0 :(得分:2)
通过消除内联视图(派生表别名为sub
)并在单个查询中完成所有工作,可以提高效率。 (这是因为MySQL处理内联视图,创建和填充临时MyISAM表的方式。)
<击>
我不明白为什么表达式date(tstarted)
需要包含在GROUP BY子句中;我没有看到删除它会改变查询返回的结果集。
击>
我现在看到将date(tstarted)
包含在内联视图查询的GROUP BY
中的效果。
我认为此查询返回与原始查询相同的结果:
SELECT SEC_TO_TIME((TIME_TO_SEC(s.tstarted) DIV 900) * 900) AS `quarter`
, SUM(s.qdelivered) AS `q`
, COUNT(DISTINCT DATE(s.tstarted)) AS `day_count`
, SUM(s.qdelivered) / COUNT(DISTINCT DATE(s.tstarted)) AS `average`
FROM statistics s
WHERE s.stat_field = 1
GROUP BY SEC_TO_TIME((TIME_TO_SEC(s.tstarted) DIV 900) * 900)
这应该更有效,因为它避免了实现中间派生表。
你的问题说你想要一天算一次&#34 ;;这听起来像是你想要计算每天在特定的四分之一小时内排的一天。
要实现这一点,您只需将聚合表达式添加到SELECT列表
即可 , COUNT(DISTINCT DATE(s.tstarted)) AS `day_count`
答案 1 :(得分:1)
我很想在当天设置一个宿舍表。使用此表并LEFT JOIN您的统计表。
CREATE TABLE quarters
(
id INT,
start_qtr INT,
end_qtr INT
);
INSERT INTO quarters (id, start_qtr, end_qtr) VALUES
(1,0,899),
(2,900,1799),
(3,1800,2699),
(4,2700,3599),
(5,3600,4499),
(6,4500,5399),
(7,5400,6299),
(8,6300,7199),
etc;
您的查询可以是: -
SELECT SEC_TO_TIME(quarters.start_qtr) AS quarter,
sum(statistics.qdelivered),
count(statistics.qdelivered),
sum(statistics.qdelivered) / count(statistics.qdelivered) as average
FROM quarters
LEFT OUTER JOIN statistics
ON TIME_TO_SEC(statistics.tstarted) BETWEEN quarters.start_qtr AND quarters.end_qtr
AND statistics.stat_field = 1
AND DATE(statistics.tstarted) = '2014-06-30'
GROUP BY quarter
ORDER BY quarter;
这样做的好处是,对于没有统计数据的季度,它将为您提供计数为0(平均值为NULL)的条目,并保存一些计算。
您可以通过向季度表添加时间列来保存更多计算: -
CREATE TABLE quarters
(
id INT,
start_qtr INT,
end_qtr INT
start_qtr_time TIME,
end_qtr_time TIME,
);
INSERT INTO quarters (id, start_qtr, end_qtr, start_qtr_time, end_qtr_time) VALUES
(1,0,899, '00:00:00', '00:14:59'),
(2,900,1799, '00:15:00', '00:29:59'),
(3,1800,2699, '00:30:00', '00:44:59'),
(4,2700,3599, '00:45:00', '00:59:59'),
(5,3600,4499, '01:00:00', '01:14:59'),
(6,4500,5399, '01:15:00', '01:29:59'),
(7,5400,6299, '01:30:00', '01:44:59'),
(8,6300,7199, '01:45:00', '01:59:59'),
etc
然后这样可以在JOIN上保存函数的使用: -
SELECT start_qtr_time AS quarter,
sum(statistics.qdelivered),
count(statistics.qdelivered),
sum(statistics.qdelivered) / count(statistics.qdelivered) as average
FROM quarters
LEFT OUTER JOIN statistics
ON TIME(statistics.tstarted) BETWEEN quarters.start_qtr_time AND quarters.end_qtr_time
AND statistics.stat_field = 1
AND DATE(statistics.tstarted) = '2014-06-30'
GROUP BY quarter
ORDER BY quarter;
这两者都假设您对某一天感兴趣。