Oracle имела в распоряжении превосходную много систему управления версиями с тех пор очень долго (по крайней мере, так как оракул 8.0)
, следующее должно помочь.
я попытался объяснить простым языком возможный... существует много к мультиуправлению версиями в базах данных.
Преобразование подзапроса в JOIN может быть довольно простым:
IN
предложение FROM TABLE_X x
WHERE x.col IN (SELECT y.col FROM TABLE_Y y)
... может быть преобразовано в:
FROM TABLE_X x
JOIN TABLE_Y y ON y.col = x.col
Ваши критерии JOIN - это то, где у вас есть прямое сравнение.
EXISTS
clause Но есть сложности, если вы посмотрите на предложение EXISTS
. EXISTS обычно коррелируют, когда подзапрос фильтруется по критериям из таблицы (таблиц) вне подзапроса. Но EXISTS предназначен только для возврата логического значения на основе критериев.
FROM TABLE_X x
WHERE EXISTS (SELECT NULL
FROM TABLE_Y y
WHERE y.col = x.col)
... преобразовано:
FROM TABLE_X x
JOIN TABLE_Y y ON y.col = x.col
Из-за логического значения существует риск того, что в наборе результатов появится больше строк.
SELECT
s в предложении SELECT Они должны всегда изменяться с предубеждением :
SELECT x.*,
(SELECT MAX(y.example_col)
FROM TABLE_Y y
WHERE y.col = x.col)
FROM TABLE_X x
Вы, вероятно, сейчас заметили скороговорку, но я сделал это немного иначе для примера встроенного представления:
SELECT x.*,
z.mc
FROM TABLE_X x
JOIN (SELECT y.col, --inline view within the brackets
MAX(y.example_col) 'mc'
FROM TABLE_Y y
GROUP BY y.col) z ON z.col = x.col
Ключ состоит в том, чтобы убедиться, что набор результатов встроенного представления включает столбцы, необходимые для соединения, вместе со столбцами.
LEFT JOIN
s Возможно, вы заметили, что у меня нет примеров LEFT JOIN - это было бы необходимо только в том случае, если столбцы из подзапроса используют тестирование NULL ( COALESCE
в наши дни почти на любой базе данных, Oracle NVL
или NVL2
, MySQL IFNULL
, SQL Server ISNULL
и т. Д.):
SELECT x.*,
COALESCE((SELECT MAX(y.example_col)
FROM TABLE_Y y
WHERE y.col = x.col), 0)
FROM TABLE_X x
Преобразовано:
SELECT x.*,
COALESCE(z.mc, 0)
FROM TABLE_X x
LEFT JOIN (SELECT y.col,
MAX(y.example_col) 'mc'
FROM TABLE_Y y
GROUP BY y.col) z ON z.col = x.col
Я не уверен, что это удовлетворит ваши типографские потребности, но надеюсь, что я продемонстрировал, что ключевым моментом является определение критериев JOIN. Как только вы знаете задействованные столбцы, вы знаете, какие таблицы используются.
SELECT x.*,
z.mc
FROM TABLE_X x
JOIN (SELECT y.col, --inline view within the brackets
MAX(y.example_col) 'mc'
FROM TABLE_Y y
GROUP BY y.col) z ON z.col = x.col
Ключ в том, чтобы убедиться, что набор результатов встроенного представления включает столбцы, необходимые для присоединения, а также столбцы.
LEFT JOIN
s Вы могли заметить, что у меня не было любые примеры LEFT JOIN - это будет необходимо только в том случае, если столбцы из подзапроса используют тестирование NULL ( COALESCE
почти на любой базе данных в наши дни, Oracle NVL
или NVL2
, MySQL IFNULL
, SQL Server ISNULL
и т. Д.):
SELECT x.*,
COALESCE((SELECT MAX(y.example_col)
FROM TABLE_Y y
WHERE y.col = x.col), 0)
FROM TABLE_X x
Конвертировано:
SELECT x.*,
COALESCE(z.mc, 0)
FROM TABLE_X x
LEFT JOIN (SELECT y.col,
MAX(y.example_col) 'mc'
FROM TABLE_Y y
GROUP BY y.col) z ON z.col = x.col
Я не уверен, что это удовлетворит ваши типографские потребности, но надеюсь, что я продемонстрировал, что ключевым моментом является определение критериев JOIN. Как только вы знаете задействованные столбцы, вы знаете, какие таблицы используются.
SELECT x.*,
z.mc
FROM TABLE_X x
JOIN (SELECT y.col, --inline view within the brackets
MAX(y.example_col) 'mc'
FROM TABLE_Y y
GROUP BY y.col) z ON z.col = x.col
Ключевым моментом является обеспечение того, чтобы набор результатов встроенного представления включал столбцы, необходимые для присоединения, а также столбцы.
LEFT JOIN
s Вы могли заметить, что у меня не было любые примеры LEFT JOIN - это будет необходимо только в том случае, если столбцы из подзапроса используют тестирование NULL ( COALESCE
почти на всех базах данных в наши дни, Oracle NVL
или NVL2
, MySQL IFNULL
, SQL Server ISNULL
и т. Д.):
SELECT x.*,
COALESCE((SELECT MAX(y.example_col)
FROM TABLE_Y y
WHERE y.col = x.col), 0)
FROM TABLE_X x
Конвертировано:
SELECT x.*,
COALESCE(z.mc, 0)
FROM TABLE_X x
LEFT JOIN (SELECT y.col,
MAX(y.example_col) 'mc'
FROM TABLE_Y y
GROUP BY y.col) z ON z.col = x.col
Я не уверен, что это удовлетворит ваши типографские потребности, но надеюсь, что я продемонстрировал, что ключевым моментом является определение критериев JOIN. Как только вы узнаете задействованные столбцы, вы узнаете, какие таблицы используются.
вместе со столбцами. LEFT JOIN
s Вы могли заметить, что у меня не было примеров LEFT JOIN - это будет необходимо только в том случае, если столбцы из подзапроса используют проверку NULL ( COALESCE
в наши дни практически на любой базе данных, Oracle NVL
или NVL2
, MySQL IFNULL
, SQL Server ISNULL
и т. Д. ):
SELECT x.*,
COALESCE((SELECT MAX(y.example_col)
FROM TABLE_Y y
WHERE y.col = x.col), 0)
FROM TABLE_X x
Преобразовано:
SELECT x.*,
COALESCE(z.mc, 0)
FROM TABLE_X x
LEFT JOIN (SELECT y.col,
MAX(y.example_col) 'mc'
FROM TABLE_Y y
GROUP BY y.col) z ON z.col = x.col
Я не уверен, что это удовлетворит ваши типографские потребности, но надеюсь, что я продемонстрировал, что ключ определяет критерии JOIN. Как только вы знаете задействованные столбцы, вы знаете, какие таблицы используются.
вместе со столбцами. LEFT JOIN
s Вы могли заметить, что у меня не было примеров LEFT JOIN - это было бы необходимо только в том случае, если столбцы из подзапроса используют проверку NULL ( COALESCE
в наши дни практически на любой базе данных, Oracle NVL
или NVL2
, MySQL IFNULL
, SQL Server ISNULL
и т. Д. ):
SELECT x.*,
COALESCE((SELECT MAX(y.example_col)
FROM TABLE_Y y
WHERE y.col = x.col), 0)
FROM TABLE_X x
Преобразовано:
SELECT x.*,
COALESCE(z.mc, 0)
FROM TABLE_X x
LEFT JOIN (SELECT y.col,
MAX(y.example_col) 'mc'
FROM TABLE_Y y
GROUP BY y.col) z ON z.col = x.col
Я не уверен, что это удовлетворит ваши типографские потребности, но надеюсь, что я продемонстрировал, что ключ определяет критерии JOIN. Как только вы знаете задействованные столбцы, вы знаете, какие таблицы используются.
нет примеров LEFT JOIN - это будет необходимо только в том случае, если столбцы из подзапроса используют тестирование NULL ( COALESCE
почти на любой базе данных в наши дни, Oracle NVL
или NVL2
], MySQL IFNULL
, SQL Server ISNULL
и т. Д.):
SELECT x.*,
COALESCE((SELECT MAX(y.example_col)
FROM TABLE_Y y
WHERE y.col = x.col), 0)
FROM TABLE_X x
Преобразовано:
SELECT x.*,
COALESCE(z.mc, 0)
FROM TABLE_X x
LEFT JOIN (SELECT y.col,
MAX(y.example_col) 'mc'
FROM TABLE_Y y
GROUP BY y.col) z ON z.col = x.col
Я не уверен, что это удовлетворит вашу типографскую потребности, но надеюсь, что я продемонстрировал, что ключевым моментом является определение критериев JOIN. Как только вы узнаете задействованные столбцы, вы узнаете, какие таблицы используются.
нет примеров LEFT JOIN - это будет необходимо только в том случае, если столбцы из подзапроса используют тестирование NULL ( COALESCE
почти на любой базе данных в наши дни, Oracle NVL
или NVL2
], MySQL IFNULL
, SQL Server ISNULL
и т. Д.):
SELECT x.*,
COALESCE((SELECT MAX(y.example_col)
FROM TABLE_Y y
WHERE y.col = x.col), 0)
FROM TABLE_X x
Преобразовано:
SELECT x.*,
COALESCE(z.mc, 0)
FROM TABLE_X x
LEFT JOIN (SELECT y.col,
MAX(y.example_col) 'mc'
FROM TABLE_Y y
GROUP BY y.col) z ON z.col = x.col
Я не уверен, что это удовлетворит вашу типографскую потребности, но надеюсь, что я продемонстрировал, что ключевым моментом является определение критериев JOIN. Как только вы узнаете задействованные столбцы, вы узнаете, какие таблицы используются.
но надеюсь, что я продемонстрировал, что ключевым моментом является определение критериев JOIN. Как только вы узнаете задействованные столбцы, вы узнаете, какие таблицы используются. но надеюсь, что я продемонстрировал, что ключевым моментом является определение критериев JOIN. Как только вы узнаете задействованные столбцы, вы узнаете, какие таблицы используются.На действительно высоком уровне. для преобразования подзапроса в JOIN:
Преобразование JOIN в подзапрос влечет за собой обратную вышеупомянутую логику
По крайней мере, в SQL Server оптимизатор может делать это по своему желанию, но я уверен, что существуют ограничения, когда он это делает. Я уверен, что это, вероятно, была чья-то докторская диссертация, чтобы иметь возможность сделать это на компьютере.
Когда я делаю это старомодным человеческим способом, это довольно просто - особенно если подзапрос уже имеет псевдоним - его можно вытащить сначала в обычное табличное выражение.
Часто это возможно, и что хорошо, так это то, что оптимизатор запросов может делать это автоматически, поэтому вам не нужно об этом заботиться.
This rates a strong "it depends".
At one level, if you're talking about queries compatible with ANSI SQL 89 or 92*, then I would guess it's a definite maybe. If you have simple (or even not so simple) queries consisting of "basic" select, from, and where clauses, then yes, I would like to think that it is mathematically possible to define processes and procedures to create and "uncreate" subqueries (though how you might determine when to algorithmically form a subquery is beyond me). I think this "rationale" could be applied to outer joins and correlated subqueries.
At another level, I'd say "no way". Most of the time I write a subquery, it's because I can't think of a way to wedge it into the "main" query. Very rarely this involves correlated subqueries, but more often than not in involves what are, I'm pretty darn sure, proprietary extensions to the standards. How could you account for pivots, unpivots, ranking functions, TOP N clauses (which may well be ANSI standards, I'll admit to never having read them cover to cover), FULL or OUTER APPLY, and the like? And that's just parts of SQL Server, I'm sure Oracle, DB2, MYSQL, and most every other player has their own extensions that break the "purist" relational model.
Of course, they say it is impossible to prove a negative. I'd summarize with "can't be done until proven otherwise", leave the proof to the academics and theoreticians, and point out that even then, whatever system you purchase won't support it unless it makes financial sense for the manufacturer to work it in. (Does any system support OUTER UNION yet?)
** A bit of googling failed to produce any references to a third ANSI SQL standard. I know I heard talk about it years ago, did it ever happen?*
A fully automatic system for transforming queries from sub-queries into joins would be relatively difficulty to build. You would need to take an input query, parse it into a parse tree and then perform some fairly complex pattern matches on the parse tree - replacing sections of the tree with new sections of the parse tree. At the end you do a traversal of the tree to output the new query.
There can be some amazingly good or bad performance repercussions. Sometimes a sub-query is much faster than a join. Sometimes it is the inverse.
Этот вопрос основан на базовых знаниях реляционной алгебры. Вы должны спросить себя, какое соединение выполняется. Например, LEFT ANTI SEMI JOIN похож на предложение WHERE NOT EXISTS.
Некоторые объединения не позволяют дублировать данные, некоторые не позволяют удалять данные. Другие позволяют использовать дополнительные поля. Я обсуждаю это в своем блоге по адресу http://msmvps.com/blogs/robfarley/archive/2008/11/09/join-simplification-in-sql-server.aspx
Также, пожалуйста, не чувствую, что вам нужно делать все в JOINs. Оптимизатор запросов должен позаботиться обо всем этом за вас, и вы часто можете значительно усложнить обслуживание запросов таким образом. Вы можете использовать обширное предложение GROUP BY и интересные фильтры WHERE .. IS NULL, который будет служить только для отсоединения бизнес-логики от дизайна запроса.
Подзапрос в предложении SELECT (по сути, поиск) предоставляет только дополнительное поле, а не дублирование или исключение. Следовательно, вам нужно убедиться, что вы применяете значения GROUP BY или DISTINCT в своем JOIN, и использовать OUTER JOIN, чтобы гарантировать такое же поведение.
Подзапрос в предложении WHERE никогда не может дублировать данные или предоставлять дополнительные столбцы в предложение SELECT, поэтому вы должны использовать GROUP BY / DISTINCT, чтобы проверить это. ГДЕ СУЩЕСТВУЕТ аналогично. (Это LEFT SEMI JOIN)
WHERE NOT EXISTS (LEFT ANTI SEMI JOIN) не предоставляет данные и не дублирует строки, но может исключить ... для этого вам нужно выполнить LEFT JOINs и искать NULL .
Но оптимизатор запросов должен сделать все это за вас. Мне действительно нравится иметь случайные подзапросы в предложении SELECT, потому что оно дает понять, что я не дублирую и не удаляю строки. QO может привести его в порядок, но если я использую представление или встроенную функцию с табличным значением, я хочу прояснить для тех, кто придет после меня, что QO может значительно упростить его. Взгляните на планы выполнения вашего исходного запроса, и вы увидите, что система предоставляет вам соединения INNER / OUTER / SEMI.
То, что вам действительно нужно избегать (по крайней мере, в SQL Server) - это функции, использующие BEGIN и END (например, скалярные функции). Может показаться, что они упрощают ваш код, но на самом деле они будут выполняться в отдельном контексте, поскольку система считает их процедурными (не упрощаемыми).
Я проводил сеанс по подобным вещам на недавней SQLBits V конференция.