Процедурно преобразуйте подзапрос в соединение

Oracle имела в распоряжении превосходную много систему управления версиями с тех пор очень долго (по крайней мере, так как оракул 8.0)

, следующее должно помочь.

  1. Пользователь A запускает транзакцию и обновляет 1 000 строк с некоторым значением При чтениях Пользователя времени B T1
  2. те же 1 000 строк во время T2.
  3. Пользователь строка обновлений 543 со значением Y (исходное значение X)
  4. Пользователь B добирается до строки 543 и находит, что транзакция в действии со Времени T1.
  5. база данных возвращает неизмененную запись из Журналов. Возвращенное значение является значением, которое фиксировалось в то время меньше чем или равное T2.
  6. , Если запись не могла бы быть получена из журналов отката, это означает, что база данных не является установкой соответственно. Должно быть больше места, выделенного к журналам.
  7. Этот путь непротиворечивость чтения достигается. Возвращенными результатами является всегда то же относительно времени начала транзакции. Таким образом в транзакции непротиворечивость чтения достигается.

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

16
задан Justin R. 8 February 2010 в 22:19
поделиться

7 ответов

Преобразование подзапроса в 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. Как только вы узнаете задействованные столбцы, вы узнаете, какие таблицы используются.

24
ответ дан 30 November 2019 в 16:09
поделиться

На действительно высоком уровне. для преобразования подзапроса в JOIN:

  1. FROM: Имена таблиц переходят в FROM
    • JOIN Части предложения WHERE с именами таблиц на обеих сторонах определяют (a) тип JOIN (b) условие соединения
    • WHERE Части предложения where без имен таблиц с обеих сторон войдите в предложение WHERE
    • SELECT Имена столбцов из подзапроса войдут в SELECT

Преобразование JOIN в подзапрос влечет за собой обратную вышеупомянутую логику

2
ответ дан 30 November 2019 в 16:09
поделиться

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

Когда я делаю это старомодным человеческим способом, это довольно просто - особенно если подзапрос уже имеет псевдоним - его можно вытащить сначала в обычное табличное выражение.

2
ответ дан 30 November 2019 в 16:09
поделиться

Часто это возможно, и что хорошо, так это то, что оптимизатор запросов может делать это автоматически, поэтому вам не нужно об этом заботиться.

3
ответ дан 30 November 2019 в 16:09
поделиться

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?*

1
ответ дан 30 November 2019 в 16:09
поделиться

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.

1
ответ дан 30 November 2019 в 16:09
поделиться

Этот вопрос основан на базовых знаниях реляционной алгебры. Вы должны спросить себя, какое соединение выполняется. Например, 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 конференция.

10
ответ дан 30 November 2019 в 16:09
поделиться
Другие вопросы по тегам:

Похожие вопросы: