MySQLは合計列を追加します
-
20-08-2019 - |
質問
この DB にクエリを実行して各行を取得するだけでなく、結果の列値の 1 つの SUM も取得する必要があります。php を使用して合計値を取得することもできますが、その場合は 2 つのループを実行する必要があります。1 つは合計を取得するためです (結果の上部に表示されます)。したがって、クエリでそれをキャッチして「合計」行を作成することを希望しますが、それを機能させる唯一の方法は、本質的に元のクエリの繰り返しであるサブクエリを使用することです。もっと良い方法はありますか?
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
これは私が必要とするものですが、おそらくそれを入手する最良の方法ではありません。
解決
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;
他のヒント
より良い方法は、コードでこれを行うことです。人々は、手続き業務を行うため、関係代数であるSQLを使用して主張し続けます。 SQLへの手続きネスを押し込もしようとすると、複雑さと性能の両面での常にの悪い考えです。 DBAプロからこのアドバイスを取ります。
あなたのコードから2人のクエリを実行します。出力最初の大規模なセット、あなたが望むものは何でも形式で合計行。あなたのクエリは、あなたのパフォーマンスが向上しますし、あなたが望む出力を得るでしょう、小さくてシンプルになります。
他のいくつかのアドバイス - ディスク容量は、安価であり、ほとんどのデータベーステーブルがはるかに頻繁に彼らが書かれているよりも読みされています。 「CONCAT(u.firstname,' ',u.lastname)
」のような計算フィールドを持つ別の列を移入し、クエリのためにそれを使用する(MySQLで可能な場合)、挿入/更新トリガを設定します。行単位の機能は、スケーラブルではありませんし、それが大きくなるにつれて、DBMSのパフォーマンスを殺すのだ。
比較すれば何でも優れている可能性があります。問題は何と比較するかですよね?
あなたが指摘した重要な問題は、合計を結果の一番上に表示したいということです。Crystal Reports やその他のアプリは、2 パス エンジンとしてこの種の魔法を管理します。最初のパスでは合計が取得されます。
どのようなソリューションにもトレードオフがあります。別の「合計」行を取得した場合、受信側アプリはそれを結果から削除するか、他のトリックを実行して非表示にする必要があります。
1 つの可能性は、1 時間あたり 100 万ヒットの Web サイト向けに書いているわけではない場合の選択肢かもしれませんが、単純に 2 つの呼び出しを行うことです。1 つは名前や合計時間などのオーバーヘッド情報用で、次に呼び出しは詳細 ...クエリからは、1 人の人の結果を選択していることがわかります。
オーバーヘッドと帯域幅を節約することには誰もが賛成しますが、場合によっては、シンプルなほうが良い場合もあります...
編集:パックスは「保存」ボタンで私を打ち負かしました...笑 ...
(私は自分自身をupvotedしました)、この目的のために、正確に提供するMySQL拡張を使用してください。
これは利用できなかった場合は、、オプション2は、別のSQL文のようになります。... SELECT SUM)SQLは本当にあなたがになりそうだループの任意の手続きコードに比べて、この種のもののために非常に効率的であるように最適化されました書きます。