2016-04-03 47 views
0

我正在使用一个小型的MariaDB数据库。每个用户提取时间间隔,我用下面的查询:如何避免SQL中重复的​​SELECT短语(MariaDB)

SELECT 
    SUM(TIMESTAMPDIFF(SECOND,Activity.startTime,Activity.endTime)) AS seconds, 
    TIME_FORMAT(SEC_TO_TIME(SUM(TIMESTAMPDIFF(SECOND,Activity.startTime,Activity.endTime))),'%Hh %im %ss') AS formattedTime, 
    TSUser.name 
FROM Activity 
INNER JOIN User ON User.id = Activity.userID 
GROUP BY User.id 
ORDER BY seconds DESC; 

我必须选择的时间以纯秒(... AS seconds)能够通过它,订购的结果可以在我的查询中可以看出。

但是,我也希望MariaDB格式化时间间隔,因为我使用TIME_FORMAT函数。问题是,我必须再次在TIME_FORMAT调用中复制整个SUM(...)短语。这看起来不太优雅。 MariaDB会识别重复并只计算一次SUM?另外,有没有办法得到相同的结果,而不复制SUM

我想这应该是可能的嵌套查询构造像这样:

SELECT 
    innerQuery.name, 
    innerQuery.seconds, 
    TIME_FORMAT(SEC_TO_TIME(innerQuery.seconds), '%Hh %im') 
FROM (
    //Do the sum here, once. 
) AS innerQuery 
ORDER BY innerQuery.seconds DESC; 

这是做/“OK”做最好的方法是什么?

注意:我不需要结果中的原始秒数,只需要格式化的时间。

我很感激帮助,谢谢。

回答

1

唉。没有一个很好的解决方案。当您使用子查询时,MariaDb将实现子查询(与MySQL一样)。您的查询相当复杂,因此无论如何都会发生大量I/O,因此额外的实现可能并不重要。

重复表达式实际上更多的是美观性而不是性能问题。该表达式将被重新执行多次。但是,进行聚合的真正花费是group by(或使用任何方法)的文件排序。执行sum()两次并不是什么大问题(除非您正在调用一个非常昂贵的函数以及聚合函数)。

其他数据库引擎不会自动实现子查询,因此在其他数据库中使用子查询通常是推荐的方法。在MariaDB/MySQL中,我猜想重复表达式会更有效率,尽管您可以尝试使用数据并回报。

1

这个的情况下,你不需要原始值。格式化的值将在ORDER BY中正常工作。

您的子查询想法可能会比较慢,因为有两个查询的所有开销。

这是一个经验法则:MySQL需要花费更多的努力才能获取一行,而不是在该行中计算表达式。用这个规则,重复的表达式不是一个负担。

+0

好的,谢谢你的建议。你是对的,上面例子中的时间格式可以用来正确地排序结果。在我的测试过程中,这失败了一次,我可能使用了不同的时间格式。 – Bensge