我想对随时间变化的系统执行SQL计算
v <- v + a (*) v
其中v
是N
个分量(N >> 10
)的向量,a
是N
乘N
的矩阵稀疏,(*)
表示矩阵乘法,并且演化是作为时间步长序列递归计算的,每个步长都使用v
的先前值。 a
随时间变化是一个外部因素,但是假设a
是恒定的,对于这个问题就足够了。
我可以用命令式语言执行此递归循环,但是基础数据有点混乱,SQL对于规范化非常出色。仅用一种语言完成工作会很整齐。
我发现矩阵乘法很好。从sqlite 3.8开始,递归也很好。但是递归循环中的矩阵乘法似乎是不可能的。这是我到目前为止的进度(也在http://sqlfiddle.com/#!5/ed521/1):
-- Example vector v
DROP TABLE IF EXISTS coords;
CREATE TABLE coords( row INTEGER PRIMARY KEY, val FLOAT );
INSERT INTO coords
VALUES
(1, 0.0 ),
(2, 1.0 );
-- Example matrix a
DROP TABLE IF EXISTS matrix;
CREATE TABLE matrix( row INTEGER, col INTEGER, val FLOAT, PRIMARY KEY( row, col ) );
INSERT INTO matrix
VALUES
( 1, 1, 0.0 ),
( 1, 2, 0.03 ),
( 2, 1, -0.03 ),
( 2, 2, 0.0 );
-- The timestep equation can also be expressed: v <- ( I + a ) (*) v, where the
-- identity matrix I is first added to a.
UPDATE matrix
SET val = val + 1.0
WHERE row == col;
-- Matrix multiply to evaluate the first step.
SELECT a.row AS row, SUM( a.val*v.val ) AS val
FROM coords v
JOIN matrix a
ON a.col == v.row
GROUP BY a.row;
在这里出现问题。我看不到没有矩阵怎么做矩阵乘法
GROUP BY
(聚合)操作,但是Sqlite3专门不允许在递归循环内进行聚合:
-- Recursive matrix multiply to evaluate a sequences of steps.
WITH RECURSIVE trajectory( row, val ) AS
(
SELECT row, val
FROM coords
UNION ALL
SELECT a.row AS row, SUM( a.val*v.val ) AS val
FROM trajectory v -- recursive sequence of steps
--FROM coords v -- non-recursive first step only
JOIN matrix a
ON a.col == v.row
GROUP BY a.row
LIMIT 50
)
SELECT *
FROM trajectory;
返回
Error: recursive aggregate queries not supported
毫无疑问,设计师有明确的理由将其排除在外!我很惊讶JOIN被允许,但是GROUP BY被禁止。不过,我不确定我有什么选择。
我还找到了其他一些递归示例,但是它们似乎都经过了精心选择的问题,对于这些问题,不需要在循环内进行聚合或自联接。在docs(https://www.sqlite.org/lang_with.html)中,示例查询以递归方式遍历树,并对输出执行avg()
。这有一点不同:聚合发生在循环外部,树遍历使用JOIN
,但递归循环内部没有聚合。仅仅因为递归不依赖于聚合,才出现该问题,就像在此问题中一样。
另一个例子,斐波那契发生器是N = 2
线性动力系统的一个例子,但是使用N = 2
,实现可以硬编码这两个值,矩阵直接乘到查询中,所以无需汇总SUM()
。一般来说,N >> 10
沿着这条路走是不可行的。
任何帮助将不胜感激。谢谢!