2014-02-16 4 views
1

Я использую рекурсивную инструкцию для выбора всего дочернего из данного родителя в таблице, представляющей структурированные записи дерева. Это в Sqlite (который теперь поддерживает рекурсивный с).
Это позволяет мне очень быстро выбрать тысячи записей в этом дереве без огромных потерь производительности из-за подготовки тысяч операторов select из вызывающего приложения.Повторное использование результатов SQL-запроса в следующем запросе в Sqlite

WITH RECURSIVE q(Id) AS 
(
    SELECT Id FROM Entity 
    WHERE Parent=(?) 
    UNION ALL 
    SELECT m.Id FROM Entity AS m 
    JOIN Entity ON m.Id=q.Parent 
) 
SELECT Id FROM q; 

Теперь предположим, что я относили данные этих лиц в произвольном числе других таблиц, которые я хочу, чтобы впоследствии загрузить. Из-за произвольного числа из них (модульным способом) невозможно включить данные, получаемые непосредственно в этом. Они должны следовать за ним.

Но если для каждой связанной таблицы я делаю инструкцию SELECT, все усиление производительности при выборе всех данных из дерева непосредственно внутри Sqlite практически бесполезно, потому что я все равно остановлюсь на тысячах последующих запросов, которые будут подготовлены каждый и выдать запрос select.

Так два вопроса:

  1. Лучшим решением сформулировать аналогичное рекурсивный утверждение для каждого из связанных таблиц, которые будут рекурсивно собирать объекты из этого дерева снова, и на этот раз выберите их соответствующие данные присоединяясь к нему. Это звучит действительно более эффективно, но это очень сложно сформулировать такое утверждение, и я немного потерял его.

  2. Теперь настоящая загадка была бы еще более эффективным решением, которое должно каким-то образом сохранить эти результаты из последнего запроса, кэшированного где-то (строки с идентификаторами из дерева сущностей), и присоединиться к ним связанных таблиц в следующем выражении, не переусердствуя снова через него?

Вот попытка в первом варианте, предположим, я хочу, чтобы выбрать поле данных из связанной таблицы компонента: это второй UNION ALL законно?

WITH RECURSIVE q(Data) AS 
(
    SELECT Id FROM Entity 
    WHERE Parent=(?) 
    UNION ALL 
    SELECT m.Id FROM Entity AS m 
    JOIN Entity ON m.Id=q.Parent 
    UNION ALL 
    SELECT Data FROM Component AS c 
    JOIN Component ON c.Id=q.Id 
) 
SELECT Data FROM q; 

ответ

1

documentation говорит:

2. В таблице с именем на левой стороне ключевого слова AS должен появиться только один раз в ЕКЕ правого наиболее ЗЕЬЕСТА соединения выберите, и нигде больше.

Так что ваш второй запрос не является законным.

Однако КТР ведет себя как обычный стол/зрение, так что вы можете просто присоединить его к соответствующей таблице:

WITH RECURSIVE q(Id) AS 
(...) 
SELECT q.Id, c.Data 
FROM q JOIN Component AS c ON q.Id = c.Id 

Если вы хотите использовать вычисленные значения в q для нескольких запросов, нет ничего вы можете делать это с помощью CTE, но вы можете хранить их во временной таблице:

CREATE TEMPORARY TABLE q_123 AS 
WITH RECURSIVE q(Id) AS 
(...) 
SELECT Id FROM q; 

SELECT * FROM q_123 JOIN Component ...; 
SELECT * FROM q_123 JOIN Whatever ...; 

DROP TABLE q_123; 
+0

Nice! Как вы думаете, для такого варианта использования (10 000 записей) создание временной таблицы будет более интересным, чем первый вариант? Я попробую эти решения и вернусь к вам – MONK

Смежные вопросы