我在表格中有一些初始行。我想用递归调用修改它们。在我的示例代码中,这个函数是一个简单的乘以2,我想执行它5次:
WITH RECURSIVE cte (n,v) AS
(
-- initial values
SELECT 0,2
UNION ALL
SELECT 0,3
UNION ALL
-- generator
SELECT n + 1, v * 2 FROM cte WHERE n < 5
)
SELECT v FROM cte where n = 5;
它有效,但我的问题是它只会在查询结束时过滤掉不需要的值。如果我从更多的行开始,它会降低性能,因为我在内存中有更多的行,因为我应该。是否可以仅在每次迭代中保留最新值?
SQLFiddle:http://sqlfiddle.com/#!5/9eecb7/6761
答案 0 :(得分:1)
在SQLite中,您可以使用OFFSET clause
- OFFSET子句,如果它存在且具有正值N, 防止前N行被添加到递归表中。该 前N行仍由递归选择处理 - 它们只是 不会添加到递归表中。行不计入 完成LIMIT直到跳过所有OFFSET行。
演示:http://sqlfiddle.com/#!5/9eecb7/6804
WITH RECURSIVE cte (n,v) AS
(
-- initial values
SELECT 0,2
UNION ALL
SELECT 0,3
UNION ALL
-- generator
SELECT n + 1, v * 2 FROM cte WHERE n < 5 LIMIT 1000 OFFSET 10
)
SELECT * FROM cte
| n | v |
|---|----|
| 5 | 64 |
| 5 | 96 |
在上面的示例中,偏移量计算为初始选择(2行)乘以迭代次数(5)=&gt;的初始行数。 2×5 = 10
顺便说一句,在这个具体的例子中,更好的解决方案是计算简单X * 2^5
(X以2到5的幂为单位)而不是递归。
答案 1 :(得分:1)
在SQLite中,CTE实现为协程(如EXPLAIN输出所示),因此只有当前行保留在内存中,性能不会因内存使用而降低。
MySQL does not allow LIMIT in the recursive SELECT part。如果我正确解释WL#3634,则8.0版中的实现总是完全实现递归CTE。
所以在SQLite中,你不需要做任何事情,而在MySQL中,你什么都做不了。