On 2. Mar 2018, at 15:55, E.Pasma <pasm...@concepts.nl> wrote: > > >> Adrián Medraño Calvo wrote: >>> The following SQL script shows a query selecting data from a >>> recursive >>> CTE and filtering it. I expected the optimizer to apply the filter >>> to >>> the recursive CTE directly, and indeed the documentation of >>> pushDownWhereTerms (src/select.c:3833) indicates this possibility >>> when >>> various conditions are satisfied. >> > Clemens Ladisch wrote: > >> Rule 22 of <http://www.sqlite.org/optoverview.html#flattening> forbids >> subquery flattening in this case. I suspect pushDownWhereTerms() is >> not >> called at all. >> > > Hello, "push down where terms" into a complex view can sometimes be > achieved by correlation. The view/CTE must then be wrapped in a new > query that is joinable via indexes. Your example is just perfect to > show the trick. E. Pasma. > > > .eqp on > WITH eqgrseq(initial, next) AS ( > SELECT push.v, pull.v > FROM t push, t pull > WHERE pull.v IN ( > WITH RECURSIVE r AS ( > SELECT push.v > UNION ALL > SELECT t.v > FROM r > JOIN t > ON t.v = r.v + 1) > SELECT v FROM r)) > SELECT initial, next > FROM eqgrseq > WHERE initial = 1; --:initial; > > Output: > --EQP-- 0,0,0,SEARCH TABLE t AS push USING COVERING INDEX > sqlite_autoindex_t_1 (v=?) > --EQP-- 0,1,1,SEARCH TABLE t AS pull USING COVERING INDEX > sqlite_autoindex_t_1 (v=?) > --EQP-- 0,0,0,EXECUTE CORRELATED LIST SUBQUERY 1 > --EQP-- 4,0,0,SCAN TABLE r > --EQP-- 4,1,1,SEARCH TABLE t USING COVERING INDEX sqlite_autoindex_t_1 > (v=?) > --EQP-- 2,0,0,COMPOUND SUBQUERIES 0 AND 0 (UNION ALL) > --EQP-- 1,0,0,SCAN SUBQUERY 2 > 1|1 > 1|2 > 1|3 > 1|4 > 1|5
Dear E. Pasma, wow, that is remarkable! The way I interpret it, by wrapping it in this way we extract the constant column out of the recursive CTE, where the WHERE clause shall not be pushed (as I learned from Dan), into the outer query, where it can be pushed. The trade-off would be that, due to it being a correlated subquery, the recursive query would be rerun for each filtered value. (I wonder whether the performance is very different from what one gets by manually inserting the WHERE clause in the base case of the recursive CTE.) I see that it could also lead to duplicate results (that is, with queries different than the example); I’d say that recursive CTEs using UNION should change to use UNION ALL plus the DISTINCT keyword on the outer query. Thank you for your answer. Sincerely, Adrián. _______________________________________________ sqlite-users mailing list sqlite-users@mailinglists.sqlite.org http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users