2017-05-10 8 views
1

1M行を超えるテーブルに対して一時的な分析クエリを実行しようとしています。典型的な質問は、任意の時間枠(例えば、過去4ヶ月など)に分割された任意の時間枠に対して、「3日ごとにグループ化された」、いくつかの行が「いくつかの基準」を満たすかどうかです。固定値リストで照会する方法

私たちの現在の解決策は、期間ごとに1つのカウントクエリを実行することです。したがって、上記の例では40の異なるクエリが生成され、パフォーマンスが許容できなくなります。私が撮影した

一つのアプローチはそうのように、一時テーブルを作成することです:

create temporary table time_series (
    lower_limit timestamp default current_timestamp, 
    upper_limit timestamp default current_timestamp 
); 

insert into time_series (lower_limit, upper_limit) values 
    ('2017-01-15 00:00:00', '2017-01-18 00:00:00'), 
    ('2017-01-18 00:00:00', '2017-01-21 00:00:00'), 
    ... 
    ('2017-05-09 00:00:00', '2017-05-12 00:00:00'), 
    ('2017-05-12 00:00:00', '2017-05-15 00:00:00'); 

select ts.upper_limit, count(mbt.time) from time_series ts 
join my_big_table mbt on 
(
    mbt.time > ts.lower_limit and 
    mbt.time <= ts.upper_limit 
) 
group by ts.upper_limit 
order by ts.upper_limit; 

drop table time_series; 

が生み出し...

+---------------------+-----------------+ 
|  upper_limit  | count(mbt.time) | 
+---------------------+-----------------+ 
| 2017-01-18 00:00:00 |   65890 | 
| 2017-01-21 00:00:00 |   98230 | 
| ...     |     | 
| 2017-05-12 00:00:00 |   57690 | 
| 2017-05-15 00:00:00 |   2349 | 
+---------------------+-----------------+ 

これは、はるかにパフォーマンスの我々の現在のソリューションよりもですが、問題は私がデータベースを所有していないことです。テーブルはOracle、SQLServer、MySQL、またはPostgreSQLのいずれかに存在する可能性があり、SELECT権限しか持たないため、一時テーブルの作成と削除は保証されません。たとえば、私は上記のSQLをMySQLで実行しましたが、CREATE TEMPORARY TABLEを自分自身に許可しなければなりませんでした。

タイムスタンプの固定リストを周期的な境界として受け入れるクエリのスコープ内で使用できる「合成テーブル」(他に何を呼び出すべきかわからない)を作成する方法はありますか?テンポラリテーブルがない場合を除いて、上記を持っているか?

+3

あなたが現在使用しているだけのDBMSにタグを付けてください。 – Sami

+0

これらのシナリオのすべてでテーブル変数を作成できると思います。 – scsimon

+0

mysqlを除くすべてのデータベースで、これをCTEで行うことができます。あなたは、あなたが照会しているRDBMSに依存して実行されるいくつかの異なる実行可能なクエリで終わるかもしれません。 – JNevill

答えて

0

コメントのすべての提案ありがとうございます。私は(私はすべてのRDBMSの間でテーブル変数を使用できるかどうかのように)あなたの提案を研究していた間、私は私が答えを見つける助けたことthis commentに出くわした:

select ts.upper_limit, count(mbt.time) from (
    select '2017-04-05 00:00:00' as lower_limit, '2017-04-10 00:00:00' as upper_limit union 
    select '2017-04-10 00:00:00' as lower_limit, '2017-04-15 00:00:00' as upper_limit union 
    select '2017-04-15 00:00:00' as lower_limit, '2017-04-20 00:00:00' as upper_limit union 
    select '2017-04-20 00:00:00' as lower_limit, '2017-04-25 00:00:00' as upper_limit union 
    select '2017-04-25 00:00:00' as lower_limit, '2017-04-30 00:00:00' as upper_limit union 
    select '2017-04-30 00:00:00' as lower_limit, '2017-05-05 00:00:00' as upper_limit union 
    select '2017-05-05 00:00:00' as lower_limit, '2017-05-10 00:00:00' as upper_limit 
) as ts 
join my_big_table mbt on 
(
    mbt.time > ts.lower_limit and 
    mbt.time <= ts.upper_limit 
) 
group by ts.upper_limit 
order by ts.upper_limit; 
0

十字結合を実行することによって125個の整数[0-124]のシーケンスを生成する(ugly!)クエリです。 、あなたは別のクエリを生成するSQLコードのこの厄介なスラグを使用することができます次に

SELECT A.N + 5*(B.N + 5*(C.N)) AS seq 
    FROM (SELECT 0 AS N UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4) AS A 
    JOIN (SELECT 0 AS N UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4) AS B 
    JOIN (SELECT 0 AS N UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4) AS C 
LIMIT 40 

:あなたはこのようなことのうち整数[0-39]を得るためにLIMIT句を使用することができます

SELECT A.N + 5*(B.N + 5*(C.N)) AS seq 
    FROM (SELECT 0 AS N UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4) AS A 
    JOIN (SELECT 0 AS N UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4) AS B 
    JOIN (SELECT 0 AS N UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4) AS C 

その中に日付範囲の束があります。

SELECT daterange.start_date + INTERVAL sequence.seq DAY lower_limit, 
     daterange.start_date + INTERVAL (sequence.seq + 3) DAY upper_limit 
    FROM (
      SELECT DATE('2017-01-15') start_date 
     ) daterange 
    JOIN (
     SELECT A.N + 5*(B.N + 5*(C.N)) AS seq 
      FROM (SELECT 0 AS N UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4) AS A 
      JOIN (SELECT 0 AS N UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4) AS B 
      JOIN (SELECT 0 AS N UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4) AS C 
     LIMIT 40 
     ) sequence 

これは、作成しようとしている一時表と同じ内容です。ですから、これを副問合せ(仮想表)として使用して、結果を得ることができます。

このクロスジョインを使用する利点は、dbmsでSELECTを行う権限が必要なことです。

追加の利点:あなたが一時テーブルを作成させないDBAに表示すると、彼女はあなたを哀れみ深くして、簡単にこれをやりなおすようにします。

MariaDB 10以上で作業している場合は、シーケンステーブルという擬似テーブルが組み込まれています。たとえば、

は、同じシーケンスの整数[0-39]を返します。これは、SQLではこのようなことをあまり冗長にしません。

+0

ありがとうO.ジョーンズ。これにより、SELECT権限制限が確実に解決されます。 3年ごとに2年、30分ごとに24時間など、任意の時間枠と期間に一般的にする方法について考える必要があります。 – chaserb

関連する問題