2016-04-03 71 views
0

私は小さなMariaDBデータベースを扱っています。ユーザーごとの時間間隔を抽出するには、私は次のクエリを使用します。SQL(MariaDB)で重複したSELECT句を避ける方法

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)としての時間を選択する必要があります。

しかし、私はまた、TIME_FORMAT関数を使用するために、MariaDBに時間間隔をフォーマットさせたいと思います。問題は、私はTIME_FORMATの中のSUM(...)のフレーズ全体を再現しなければならないということです。これはあまりエレガントではないようです。 MariaDBは重複を認識してSUMを1回だけ計算しますか?また、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()を2回実行するのは大したことではありません(本当に高価な関数と集約関数を呼び出さない限り)。

他のデータベースエンジンではサブクエリが自動的にマテリアライズされないため、通常は他のデータベースでサブクエリを使用することをお勧めします。 MariaDB/MySQLでは、表現を繰り返す方が効率的ですが、データとレポートの両方を試すことができます。

1

このの場合、生の値は必要ありません。書式設定された値はORDER BYで正しく機能します。

サブクエリの考え方は、2つのクエリのオーバーヘッドのために遅くなる可能性があります。

これはThumbのルールです:行内の式を評価するよりも、MySQLが行をフェッチするのにはるかに時間がかかります。このルールでは、重複する表現は負担にはなりません。

+0

申し訳ありませんが、アドバイスありがとうございます。あなたは正しいです、上記の例の時間形式は、結果を正しくソートするために使用できます。私のテストではこれは一度は失敗しましたが、おそらく別の時刻形式を使用していました。 – Bensge

関連する問題