2017-08-29 8 views
0

いくつかのUNION ALLを集計するサブクエリがあります。私はSELECTを用意してクロスタブを作成し、20とするように制限しています。メインクエリで制限する前に、サブクエリ結果の合計COUNTを取得できるようにしたいと考えています。これは、レコードの総数とそれに続く特定のページレコードグリッドを受け取るページネーションを作成しようとするためです。LIMIT(クリックハウス)を適用する前のサブクエリのSELECTカウント

サンプルクエリ:

SELECT 
    name, 
    sumIf(metric_value, metric_name = 'data') AS data, 
    sumif(.... 
FROM 
    (SELECT 
     name, metric_name, SUM(metric_value) as metric_value 
    FROM 
     (SELECT 
       name, 'data' AS metric_name, SUM(data) AS metric_value 
      FROM 
       table 
      WHERE 
       date > '2017-01-01 00:00:00' 
      GROUP BY 
       name 

      UNION ALL 

      SELECT 
       name, 'data' AS metric_name, SUM(data) AS metric_value 
      FROM 
       table2 
      WHERE 
       date > '2017-01-01 00:00:00' 
      GROUP BY 
       name 

      UNION ALL 

      SELECT 
       name, 'data' AS metric_name, SUM(data) AS metric_value 
      FROM 
       table3 
      WHERE 
       date > '2017-01-01 00:00:00' 
      GROUP BY 
       name 

      UNION ALL 

      . 
      . 
      .) 
    GROUP BY 
     name, metric_name) 
GROUP BY 
    name 
ORDER BY 
    name ASC 
LIMIT 0,20; 

第一副選択は、データのトンを返すので、私はそれをカウントし、1つの列値として返し、又は行とそれが20の結果を制限選択主に伝搬することができると思いました。私は結果の全セットを知っている必要があるが、ドントを知る必要があるので、同じクエリを制限なしに2回呼び出すだけで、COUNTを得るには限界がある。少なくとも12のUNION ALLの第3レベルのサブ選択があるので、なぜ無駄なリソースですか。私は一般的なSQLソリューションをClickHouseに必ずしも関連しないようにしようとしています

私はcount(*) OVER()を使用することを考えていましたが、サポートされていません。

+0

んSQL_CALC_FOUND_ROWSの助けである場合:私は理解して、このようなものでしょうか?このシナリオは、そのために設計されたものです。そのオプションでクエリを実行すると、SELECT FOUND_ROWS()はLIMITが適用される前に(クエリを再実行せずに)行の総数を返します。 https://dev.mysql.com/doc/refman/5.7/en/information-functions.html#function_foundrows – EdmCoff

+0

同じユニオンのサブクエリに参加したいかもしれませんが、今度は結果の数を取得してください。 – Lamar

+0

ご意見ありがとうございました。私はSQL_CALC_FOUND_ROWSが存在するかどうか分かりませんでした。コマンドをサポートしているデータベースを使用している人にとって、この問題は解決します。私が使用しているClickHouseは列ベースであり、実装されていません。 – OscarHanzely

答えて

0

最初に言及する必要があるのは、誰も通常、クエリの正確なページ数に関心がないということです。それは容易に推定することができ、推定はどれほど正確であるかを気にする人はほとんどいません。ただし、GUIの最後のページへのリンクがある場合、リンクをクリックしてそのリンクが機能しているかどうかを確認することがよくあります。

しかし、アナリストがすべてのページを訪問する必要があり、GUIに正確な作業量が表示されることがあります。良いことは、後者の場合、より良い戦略は、結果テーブル全体のスナップショットをキャッシュし、テーブル内の行数をカウントすることがもはや問題にならないことです。

つまり、1日に何回も不要なフルスキャンがデータベースの負荷と請求額の合計に影響を及ぼす可能性があるため、顧客に本当に必要かどうかについて話し合うのは理にかなっています。

とにかく、行数を見積もる必要がある場合は、単に行数を数えるためにクエリを単純化することができます。

SELECT SUM(cnt) as row_count 
FROM (
    SELECT COUNT(DISTINCT name) as cnt FROM table1 WHERE date > ... 
    UNION ALL 
    SELECT COUNT(DISTINCT name) as cnt FROM table2 WHERE date > ... 
    ... 
) as counts; 

またはdataが一定のメトリック名

SELECT COUNT(DISTINCT name) as row_count 
FROM (
    SELECT DISTINCT name FROM table1 WHERE date > ... 
    UNION ALL 
    SELECT DISTINCT name FROM table2 WHERE date > ... 
    ... 
) as names; 
+0

ありがとうございます@newtover、私は以前と同じ声明を読んで、あなたが正しいと私は正確な結果/ページを知る必要はないことに同意し、これはシステムの主なパラメータとして統計データをカウントするために使用されます。つまり、グループ化されたSQLの結果の最大量は5000未満であると予想され、日付制限のために平均でクライアントは数百だけのデータを取得する可能性があります。それは簡単にそれらの数ページのレコードを見ることができ、最後のページで問題を引き起こす可能性があるため正確にする必要があります。 – OscarHanzely

+0

あなたの提案はかなり理論を要約しています。私は完全な結果を得るために同じ構造の個別のコマンドをデータベース上で実行する必要があります。 Countは役に立ちますが、ロードはまだそこにあります。サブクエリの結果をキャッシュすると、ClickHouseを探しています。サブクエリの結果をキャッシュすると、2回実行するのは大したことになりません。しかし、私たちが処理する行の量は、分散した断片に対して約20百万と推定されます。そのためには、いくつかのパフォーマンステストが必要です。 – OscarHanzely

関連する問題