我有一个查询,它返回令牌具有特定分类的概率。
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 :(得分:2)
通常,如果SQLite不能这样做,您可以编写自定义函数。详细信息取决于您使用的编程语言,这里使用DBD::SQLite在Perl中。请注意,以这种方式创建的函数不是存储过程,它们存在于该连接中,每次连接时都必须重新创建。
对于聚合函数,您必须创建一个处理聚合的类。 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"
);
同样,细节会因您的特定语言而有所不同,但基本想法将是相同的。
这比获取每一行并获取聚合产品要快得多。
答案 1 :(得分: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