2017-04-06 9 views
1

トークンに特定の分類がある確率を返すクエリがあります。SQLiteでグループ内の行を掛ける

token  class  probPaired 
---------- ---------- ---------- 
potato  A   0.5 
potato  B   0.5 
potato  C   1.0 
potato  D   0.5 
time  A   0.5 
time  B   1.0 
time  C   0.5 

classの確率をまとめて掛け合わせる必要があります。

-- Imaginary MUL operator 
select class, MUL(probPaired) from myTable group by class; 

class  probability 
---------- ---------- 
A   0.25 
B   0.5 
C   0.5 
D   0.5 

SQLiteでこれを行うにはどうすればよいですか? SQLiteは、LOG/EXPや変数 - ソリューションmentioned in other questionsのような機能を持っていません。

+0

@GurVこれらの答えは、回避策を実装するために、[それはLOGやEXPを欠い](https://sqlite.org/lang_corefunc.html)、SQLiteのには適用されません。 – Schwern

答えて

1

行番号を計算し、乗算に再帰的なcteを使用できます。次に、乗算の最終結果を含む各クラスのmax rnum(計算されたrow_number)値を取得します。

--Calculating row numbers 
with rownums as (select t1.*, 
       (select count(*) from t t2 where t2.token<=t1.token and t1.class=t2.class) as rnum 
       from t t1) 
--Getting the max rnum for each class 
,max_rownums as (select class,max(rnum) as max_rnum from rownums group by class) 
--Recursive cte starts here 
,cte(class,rnum,probPaired,running_mul) as 
    (select class,rnum,probPaired,probPaired as running_mul from rownums where rnum=1 
    union all 
    select t.class,t.rnum,t.probPaired,c.running_mul*t.probPaired 
    from cte c 
    join rownums t on t.class=c.class and t.rnum=c.rnum+1) 
--Final value selection 
select c.class,c.running_mul 
from cte c 
join max_rownums m on m.max_rnum=c.rnum and m.class=c.class 

SQL Fiddle

2

一般的に、SQLiteで実行できない場合は、代わりにカスタム関数を記述することができます。詳細は使用しているプログラミング言語に依存します。ここではPerlでDBD::SQLiteを使用しています。この方法で作成される関数はストアドプロシージャではなく、その接続用に存在し、接続するたびに再作成する必要があることに注意してください。

集計関数では、集計を処理するクラスを作成する必要があります。 MULは非常にシンプルで、製品を保管するためのオブジェクトです。

{ 
    package My::SQLite::MUL; 

    sub new { 
     my $class = shift; 
     my $mul = 1; 
     return bless \$mul, $class; 
    } 

    sub step { 
     my $self = shift; 
     my $num = shift; 

     $$self *= $num; 

     return; 
    } 

    sub finalize { 
     my $self = shift; 

     return $$self; 
    } 
} 

その後は、単一の引数を取り、そのクラスを使用する集約関数MULとしてそれをインストールしたいです。

my $dbh = ...doesn't matter how the connection is made... 

$dbh->sqlite_create_aggregate("MUL", 1, "My::SQLite::MUL"); 

これでクエリでMULを使用できます。

my $rows = $dbh->selectall_arrayref(
    "select class, MUL(probPaired) from myTable group by class" 
); 

また、詳細はご使用の言語によって異なりますが、基本的な考え方は同じです。

これは、各行をフェッチして集計するよりもはるかに高速です。

関連する問題