MySQL添加总列
Posted
技术标签:
【中文标题】MySQL添加总列【英文标题】:MySQL add total column 【发布时间】:2010-10-04 03:28:38 【问题描述】:我需要查询此数据库以获取每一行,以及结果的列值之一的总和。我可以使用 php 来获取总值,但是我需要运行两个循环,一个来获取总值(位于结果上方的顶部)。所以我更喜欢查询来捕获它并只创建一个“总”行,但我让它工作的唯一方法是使用基本上是原始查询重复的子查询。有没有更好的办法?
SELECT
CONCAT(u.firstname, ' ', u.lastname ) name, u.id, s.description, s.shiftstart, s.shiftend,
(SELECT
SUM( TIME_TO_SEC( TIMEDIFF( shiftend, shiftstart ) ) ) /3600
FROM shifts
WHERE id = '$user'
AND DATE( shiftstart )
BETWEEN '$start'
AND '$end') total
FROM shifts s
INNER JOIN users u ON ( s.id = u.id )
WHERE s.id = '$user'
AND DATE( shiftstart )
BETWEEN '$start'
AND '$end'
ORDER BY shiftstart
以上工作和输出:
name id description shiftstart shiftend total
Joe User joeuser Stuff 2009-01-05 07:45:00 2009-01-05 12:15:00 39.5000
Joe User joeuser Stuff 2009-01-05 13:00:00 2009-01-05 17:00:00 39.5000
Joe User joeuser Stuff 2009-01-06 07:45:00 2009-01-06 10:45:00 39.5000
Joe User joeuser Stuff 2009-01-06 10:45:00 2009-01-06 12:45:00 39.5000
Joe User joeuser Stuff 2009-01-06 13:30:00 2009-01-06 14:30:00 39.5000
Joe User joeuser Stuff 2009-01-06 14:30:00 2009-01-06 17:00:00 39.5000
Joe User joeuser Stuff 2009-01-07 09:45:00 2009-01-07 14:00:00 39.5000
Joe User joeuser Stuff 2009-01-07 15:00:00 2009-01-07 17:00:00 39.5000
Joe User joeuser Stuff 2009-01-08 08:00:00 2009-01-08 12:15:00 39.5000
Joe User joeuser Stuff 2009-01-08 13:15:00 2009-01-08 17:00:00 39.5000
Joe User joeuser Stuff 2009-01-09 07:45:00 2009-01-09 10:45:00 39.5000
Joe User joeuser Stuff 2009-01-09 11:45:00 2009-01-09 15:15:00 39.5000
Joe User joeuser Stuff 2009-01-09 15:15:00 2009-01-09 17:00:00 39.5000
这是我需要的,但可能不是获得它的最佳方式。
【问题讨论】:
【参考方案1】:使用专门为此目的提供的 mysql 扩展,如 Bill Karwin 的回复(我自己赞成)中所述。
如果这不可用,选项 2 将是另一个 SQL 语句:SELECT SUM ...) 与您可能使用的任何过程代码循环相比,SQL 确实经过优化,可以非常有效地处理此类事情写。
【讨论】:
【参考方案2】:MySQL 支持称为ROLLUP 的特殊分组修饰符。
SELECT CONCAT(u.firstname, ' ', u.lastname ) name, u.id,
s.description, s.shiftstart, s.shiftend,
SUM( TIME_TO_SEC( TIMEDIFF( shiftend, shiftstart ) ) ) /3600 total
FROM shifts s INNER JOIN users u ON ( s.id = u.id )
WHERE s.id = ? AND DATE( shiftstart ) BETWEEN ? AND ?
GROUP BY u.id, s.shiftstart WITH ROLLUP
ORDER BY shiftstart;
【讨论】:
【参考方案3】:相比之下,任何事情都可以更好;问题是与什么比较,对吧?
您指出的关键问题是您希望总数位于结果的顶部; Crystal Reports 和其他应用程序通过作为 2 通道引擎来管理这种魔法。第一次通过获得总数。
任何解决方案都需要权衡取舍。如果您得到一个单独的“总计”行,那么接收应用程序将需要将其从结果中删除或使用其他技巧来隐藏它。
如果您不是为每小时点击量 100 万次的网站编写代码,则一种可能性是简单地拨打 2 次电话,其中一次用于获取开销信息,例如名称、总时间等,然后查看详细信息...从查询中显示您正在选择一个人的结果。
我们都是为了节省开销和带宽,但有时,简单更好......
编辑:Pax 将我击败到“保存”按钮...大声笑...
【讨论】:
【参考方案4】:更好的方法是使用代码来实现。人们一直坚持使用关系代数 SQL 来完成程序性任务。就复杂性和性能而言,试图将过程性硬塞到 SQL 上总是是个坏主意。听取专业 DBA 的建议。
从您的代码中运行两个查询。首先输出较大的集合,然后以您想要的任何格式输出总行。您的查询将变得更小更简单,您的性能将得到提高,并且您将获得所需的输出。
其他一些建议 - 磁盘空间很便宜,并且大多数数据库表的读取频率远高于写入频率。设置插入/更新触发器(如果可能在 MySQL 中)以使用“CONCAT(u.firstname,' ',u.lastname)
”等计算字段填充单独的列,并将其用于查询。每行函数不可扩展,并且会随着 DBMS 变大而降低性能。
【讨论】:
更好的方法取决于 SQL 服务器和 PHP 服务器之间可用 CPU 时间的平衡,这可以在任何给定环境中采用任何一种方式。当我知道我有一个专用于相关应用程序的 SQL 服务器和一个大规模共享的 PHP 服务器时,我经常卸载非常程序化的过程。 如果您的 DBMS 是具有备用容量的数据库管理系统,@Sparr,请使用存储过程以您想要的顺序返回记录(从两个更快、更易于编写和理解查询)。这仍然是代码,仍然比硬塞更好。以上是关于MySQL添加总列的主要内容,如果未能解决你的问题,请参考以下文章