Чи додають підзапроси виразну силу до SQL-запитів?


29

Чи потрібні SQL підзапити?

Уявіть достатньо узагальнену реалізацію структурованої мови запитів для баз даних відношень. Оскільки структура канонічного оператора SQL SELECTнасправді є досить важливою для цього, щоб мати сенс, я не звертаюсь безпосередньо до реляційної алгебри, але ви могли це обрамлити в цих термінах, зробивши відповідні обмеження форми виразів.

SQL - SELECTзапит , як правило , складається з виступу ( SELECTчастина) деякої кількості JOINоперацій (далі JOINчастина), деяка кількість SELECTION операцій (в SQL, в WHEREпунктах), а потім встановити-навхрест операції ( UNION, EXCEPT, INTERSECTі т.д.), за яким слідує інший SQL- SELECTзапит.

Об'єднані таблиці можуть бути обчисленими результатами виразів; Іншими словами, ми можемо мати таке твердження, як:

SELECT t1.name, t2.address
  FROM table1 AS t1 
  JOIN (SELECT id, address 
          FROM table2 AS t3 
         WHERE t3.id = t1.id) AS t2
 WHERE t1.salary > 50,000;

Ми будемо посилатися на використання обчисленої таблиці як частини SQL-запиту як підзапиту. У наведеному вище прикладі другий (з відступом) SELECT- це запит.

Чи всі запити SQL можуть бути записані таким чином, щоб не використовувати підзапити? Наведений вище приклад може:

SELECT t1.name, t2.address
  FROM table1 AS t1 
  JOIN table2 AS t2
    ON t1.id = t2.id
 WHERE t1.salary > 50,000;

Цей приклад є дещо хибним або тривіальним, але можна уявити випадки, коли для відновлення еквівалентного вираження може знадобитися значно більше зусиль. Іншими словами, чи буває так, що для кожного запиту SQL з підзапитами існує запит q ' без підзапитів, таким, що q і q ' гарантовано дають однакові результати для одних і тих же базових таблиць? Обмежимо запити SQL у такій формі:qqqq

SELECT <attribute>,
      ...,
      <attribute>
 FROM <a table, not a subquery>
 JOIN <a table, not a subquery>
  ...
 JOIN <a table, not a subquery>
WHERE <condition>
  AND <condition>
  ...
  AND <condition>

UNION
 -or-
EXCEPT
 -or-
<similar>

SELECT ...

І так далі. Я думаю, що лівий і правий зовнішні з'єднання не дуже додають, але якщо я помиляюся, будь ласка, не соромтесь зазначити це ... у будь-якому випадку, вони також є чесною грою. Що стосується заданих операцій, я думаю, що будь-яка з них нормальна ... з'єднання, різниця, симетрична різниця, перетин тощо ... все, що є корисним. Чи є відомі форми, до яких можна зменшити всі запити SQL? Чи усуває будь-який із цих запитів? Або є випадки, коли не існує еквівалентного запиту без підзапитів? Посилання вдячні ... або демонстрація (на підтвердження) того, що вони є або не потрібні, була б фантастичною. Дякую і вибачте, якщо це видатний (або тривіальний) результат, який я болісно не знаю.


5
Мій кишечник говорить мені, що ти завжди можеш об'єднати все і вибирати звідти до тих пір, поки тобі не знадобляться зведені значення. Вибір усіх записів зі значенням, більшим за середнє для його стовпця, схоже, спочатку потребує обчислення середнього рівня, тому потрібен підзапит.
Рафаель

@Raphael Я досить впевнений, що ви навіть можете робити зведені значення, вам просто потрібно зробити більше самоз'єднань і групових бай (роблячи це експоненціально більшим, але все ж можливим). Не впевнений, як я офіційно доводжу, що ти можеш все зробити так.
Кевін

@Kevin Ви впевнені, що кількість необхідних операцій не залежить від кількості рядків? Тому що ми не можемо цього мати, чи не так?
Рафаель

1
Нормальний приклад я для вимагає підзапиту розраховують дублікати: select count(*) from (select id from sometable group by id having count(*)>1) d. Оскільки це включає, group byя не ставлю це як відповідь.
Марк Херд

BTW AFAIK у звичайному SQL ONзастереження необхідне для JOINs, хоча перехресний добуток виходить лише з комою.
Марк Херд

Відповіді:


9

Існує деяка термінологічна плутанина; блок запиту в дужках

SELECT t1.name, t2.address
  FROM table1 
  JOIN (SELECT id, address 
          FROM table2 AS t3 
         WHERE t3.id = t1.id) 

називається внутрішнім зором . Підзапит є блок запиту в межах або WHERE або ВИБРАТИ положення, наприклад ,

select deptno from dept
where 3 < (select count(1) from emp 
           where dept.deptno=emp.deptno)

У будь-якому випадку внутрішній вигляд або підзапит можуть бути відменені в "плоский" проект-обмежити-об'єднати. Співвіднесений підзапит з агрегуванням не потребує внутрішніх поглядів з групуванням, який потім перетворюється на плоский запит.

select deptno from dept d
    where 3 < (select avg(sal) from emp e
               where d.deptno=e.deptno)

select d.deptno from dept d, ( 
    select deptno from emp e
    group by deptno
    having avg(sal) > 3
) where d.deptno=e.deptno

select d.deptno from dept d, emp e
where d.deptno=e.deptno 
group by d.deptno
having avg(sal) > 3

Що стосується алгебраїчних правил оптимізації запитів, то, як відомо, реляційна алгебра є аксіоматизованою в реляційну решітку, що спрощує перетворення запитів, як показано тут і там .


Мені цікаво. Чи можете ви додати приклад запиту, який використовує деякі поля середнього рівня, наприклад, вибір усіх записів із значенням вище середнього? Мені незрозуміло, як це виглядало б після вирівнювання.
Рафаель

16

Щоб перевести ваше твердження в реляційну алгебру, я думаю, що він запитує:

σA(A)σB(B)σA(σB(AB))

σ

Відповідь "Так", і це стандартна оптимізація запитів. Якщо чесно, я не впевнений, як довести це непросимо - це лише властивість вибору та приєднання. Ви можете індуктивно сперечатися додавати скільки завгодно шарів вкладених запитів.

Крім того, ви можете запитати:

ABC(AB)(CD)

Знову відповідь - так, тому що приєднання асоціативне. Подібні твердження можна зробити і щодо проекції.

Один із помітних типів "підзапиту", який, на мою думку, не можна "вирівняти" - це with. Один із способів переконатися в цьому - зазначити, що якщо у вас є withоператор, то ви можете мати рекурсивну функцію, яку неможливо записати без використання підзапитів.

Отже, підсумовуючи: у конкретному випадку, який ви згадали, ні, SQL не потрібні підзапити, і ви можете це довести індуктивно. Взагалі, однак, є функції, які вимагають підзапитів.


Рекурсивна поведінка через withбуло введено в SQL: 1999, і робить отриману мову строго більш виразною.
Андраш Саламон

1

"Чи додають підзапроси виразну силу до SQL-запитів?"

Вони зробили, принаймні до введення EXCEPT мовою SQL.

До введення EXCEPT не було можливості висловити різницю різниці або напіввідмінність у SQL, не вдаючись до підзапитів.

У ці дні всі "типові" примітивні оператори "" реляційної алгебри можуть бути виражені без підзапитів:

NATURAL JOIN можна зробити з допомогою NATURAL JOIN або JOIN ON
UNION можна зробити з допомогою UNION
МІНУС можна зробити через КРІМ
PROJECT / перейменовувати / подовжити можна зробити через в SELECT ,
Обмежити можна зробити з допомогою WHERE
реляційних литералов може бути зроблений через ЗНАЧЕННЯ
транзитивних замикання можуть робити через рекурсивний З

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.