Общее табличное выражение в подзапросе - PullRequest
7 голосов
/ 25 июля 2011

Я хотел бы попросить помощи в понимании того, какие все СУБД из Oracle, DB2, Sybase поддерживают общее табличное выражение (CTE) в подзапросе.Я знаю, что PostgreSQL делает, а MS SQL Server нет.

SELECT a.*, b.* 
 FROM (WHERE aa as (
          <<select_query>),
          SELECT * 
            FROM aa
           WHERE <<criteria>>
    ) as a
    LEFT JOIN (
        WITH bb as (
            <<select_query>
        ),
        select * from bb inner join tbl_c on <<innerjoin>> where <<criteria>>
    ) as b
    on <<join_expr>>

Я не могу определить предложение with вне подзапросов - оба запроса генерируются динамически с учетом столбцов, критериев, безопасности,и т.д. Также вышеупомянутый запрос может использоваться в другом запросе как подзапрос.Таким образом, принцип - это динамически генерируемые представления, которые можно использовать позже.Некоторые запросы могут иметь до 10-12 таких динамических представлений, которые также объединяются.Проблема в том, что приложение должно быть независимым от базы данных, по крайней мере, в том, что касается PG, Oracle и DB2, а функции, не поддерживаемые одним из них, вообще не реализованы.

Ответы [ 4 ]

4 голосов
/ 25 июля 2011

Да, вы можете использовать CTE в подзапросах в Oracle. Из документов Oracle 11g :

Вы можете указать это предложение в любом операторе SELECT верхнего уровня и в большинство типов подзапросов. Имя запроса видно для основного запроса и ко всем последующим подзапросам. Для рекурсивного факторинга подзапроса, имя запроса даже видно подзапросу, который определяет запрос Назови себя.

Например, это работает в Oracle:

SELECT a.*, b.*
  FROM (WITH aa AS
         (
           SELECT LEVEL l1, mod(level, 5) m1 FROM dual CONNECT BY LEVEL < 50
         )
         SELECT * FROM aa WHERE m1 < 3) a LEFT JOIN
       (WITH bb AS 
         (
           SELECT LEVEL l2, mod(level, 5) m2 FROM dual CONNECT BY LEVEL < 50
         )
         SELECT * FROM bb WHERE m2 BETWEEN 1 AND 4) b
        ON a.l1 = b.l2;
3 голосов
/ 25 июля 2011

Это не является прямым ответом на ваш вопрос, но, возможно, вы можете подумать об этом:

Кажется, что SQL Server ограничивает семантику (не обязательно синтаксис) SQL, где имеет смысл это делать.Например, вы не можете иметь подзапрос с предложением ORDER BY, если вы также не укажете предложение TOP n.Это имеет смысл, поскольку упорядоченные подзапросы бессмысленны, если у них нет ограничений.Другие СУБД допускают такую ​​бессмысленность.

В вашем случае (это всего лишь предположение) наличие CTE в подзапросах имеет лишь ограниченный смысл, поскольку вы можете переписать весь запрос так, чтобы CTE были объявлены в верхней части.самый высокий уровень.Единственное различие, которое у вас будет, - это объем и, возможно, читаемость каждого объявления.

С другой стороны, CTE допускает рекурсивные запросы, которые могут быть очень трудны для применения, когда CTE объявляются в подзапросах.

Поскольку вам необходимо реализовать независимый от базы данных SQL, я рекомендую вам пока не использовать CTE интенсивно.Если CTE простые, вы всегда можете переписать их как простые представления ...

0 голосов
/ 06 февраля 2014

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

0 голосов
/ 06 февраля 2014

Более новые версии Microsoft SQL Server поддерживают CTE.

...