powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Подзапрос = обычная таблица в запросе?
9 сообщений из 9, страница 1 из 1
Подзапрос = обычная таблица в запросе?
    #32048937
Фотография toypaul
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Хотелось бы узнать у уважаемых форумистов является ли
подзапрос полным эквивалентом обычной таблицы в запрсе.
Что я под этим понимаю? Применимы ли к результату подзапроса
все операции что и к обычной таблице. То есть соединение
с другими таблицами, объединение, группировка по полям, сортировка
агрегатные функции. Понятно, что результат подзапроса
представляет собой с точки зрения теории ту же реляционную
таблицу, но будут ли применимы к ней ВСЕ операции (все ключевые
слова, функции и т.п.).

Есть ли какие-то ограничения на использование подзапросов
в определенных конструкциях? Есть ли такие места где обычная
таблица может использоваться, а подзапрос нет?

Почему я это спрашиваю. Передо мной стоит задача перевод с
собственного языка запросов в T-SQL. В моем языке запросов
будут иметь место такие конструкции, когда нужно будет
запись к одному объекту заменить не напрямую на запрос к
одной таблице, а на запрос к нескольким таблицам (то есть на
некоторый подзапрос). Сделать это можно двумя способами:

1. (Как делаю я сейчас) Запрос типа

select a.b,c.d from a,c where a.e = c.f

заменять на такую конструкцию

select a.b,c_1.d
from a,c_1 where a.e = c_1.f
union all
select a.b,c_2.d
from a,c_2 where a.e = c_2.f

Надеюсь пример понятен - то есть всю простые таблицы мы
вносим внутрь сложного запроса

2. Как хотелось бы (так проще)

select a.b,c_1.d
from a,
(
select c_1.d,c_1.f from c_1
union all
select c_2.d,c_2.f from c_2
) c
where a.e = c.f

Во втором случае также меня терзают сомнения насчет
эффетивности. Дело в том, что в общем запрос мы может писать
так

select a.b,c.d from a,c
where a.e = c.f and a.l = 1000

То есть задаем некое ограничение, которое в первом случае будет
также переносится в каждую составляющую union, во втором же
случае фильтрация будет осущствляться позже. Хотя может быть
во втором случае оптимизатор сможет найти зависимость и внесет
ограничение внутрь подзапроса? Это меня также волнует может быть
даже больше чем ограничения на использование подзапросов

Вот так вот. Длинно, но думаю понятно.
...
Рейтинг: 0 / 0
Подзапрос = обычная таблица в запросе?
    #32048949
Glory
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Есть ли какие-то ограничения на использование подзапросов в определенных конструкциях? Есть ли такие места где обычная таблица может использоваться, а подзапрос нет?

Ограничения, конечно, есть
BOL - Accessing and Changing Relational Data - Advanced Query Concepts - Subquery Fundamentals - Subquery Rules

Хотя может быть во втором случае оптимизатор сможет найти зависимость и внесет ограничение внутрь подзапроса?

Всегда можно идти от обратного:
имееются запросы такого типа, как "заставить" оптимизатор выбрать наилучшиий план выполнения.
Либо неявно - с помощью создания тех же индексов
Либо явно - с помощью хинтов.
...
Рейтинг: 0 / 0
Подзапрос = обычная таблица в запросе?
    #32048951
Фотография toypaul
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ограничения, конечно, есть
BOL - Accessing and Changing Relational Data - Advanced Query Concepts - Subquery Fundamentals - Subquery Rules

Спасибо. Не понятны следующие пункты:

If the WHERE clause of an outer query includes a column name, it must be join-compatible with the column in the subquery select list.

Because they must return a single value, subqueries introduced by an unmodified comparison operator (one not followed by the keyword ANY or ALL) cannot include GROUP BY and HAVING clauses.

ORDER BY can only be specified if TOP is also specified (понятно, но не понятно почему такое ограничение)


Всегда можно идти от обратного:
имееются запросы такого типа, как "заставить" оптимизатор выбрать наилучшиий план выполнения.
Либо неявно - с помощью создания тех же индексов
Либо явно - с помощью хинтов.

Нет. Здесь немного другая проблема, которая индексами и хинтами не решается. Скажем вот в таком запросе:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
select a.b,c_1.d 
from a, 
( 
select c_1.d,c_1.f from c_1 
union all 
select c_2.d,c_2.f from c_2 
) c 
where a.e = c.f  and a.l =  100 


поймет ли оптимизатор, что не стоит выполнять ползапрос по всем строкам, а только по тем, которые в таблице a удовляеторяют условию and a.l = 100. В таблицах c_1,c_2 может быть миллион записей, но накладывая условие and a.l = 100 мы может ограничить их количество до 1. Вот в чем вопрос.
...
Рейтинг: 0 / 0
Подзапрос = обычная таблица в запросе?
    #32048954
Glory
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Давайте определися для начала
subquery - это subquery
derived table - это derived table

Ссылка в BOL именно для subquery.

поймет ли оптимизатор, что не стоит выполнять ползапрос по всем строкам, а только по тем, которые в таблице a удовляеторяют условию and a.l = 100.

Условие a.l = 100 не накладывает никаких ограничений на derived table, полученную из таблиц c_1 и c_2.
Для того, чтобы выяснить, имеется ли в derived table какая-нибудь запись из таблицы "а", нужно оперировать со всей derived table. А вот каким образом будет осуществляться join между "а" и derived table можно попробовать регулировать с помощью индексов и хинтов.
Вполне вероятно, что для derived table, полученных из объединения нескольких таблиц, в оптимизации запроса могут помочь и partitioned views (но это если версия позволяет).

Конечно, оптимизатор не идеален, так что, если можете помочь ему, то помогайте.
Например, если вам известно, что для записей с a.l = 100 имеются записи только в таблице c_2, то и стройте свой запрос соответсвующим образом (все рано вы ведь делаете это динамически ?)
...
Рейтинг: 0 / 0
Подзапрос = обычная таблица в запросе?
    #32048956
Фотография toypaul
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вобщем либо я не врубаюсь, либо вы (ты). Еще раз.
Имеем запрос на моем языке

Код: plaintext
1.
2.
select a.b,c.d
from a,c
where a.e = c.d and a.l =  100 


который переводится в запрос на T-SQL двумя способами

1) Как мне хотелось бы.

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
select a.b,c.d 
from a, 
( 
select c_1.d,c_1.f from c_1 
union all 
select c_2.d,c_2.f from c_2 
) c 
where a.e = c.f  and a.l =  100 


Поясню почему. Потому что таблица "с" в запросе
просто заменяется на подзапрос/или подчиненную таблицу - здесь
без разницы.

2) Как делаю сейчас

Код: plaintext
1.
2.
3.
4.
select a.b,c_1.d from c_1,a
where a.e = c_1.f and a.l =  100 
union all
select a.b,c_2.d from c_2,a
where a.e = c_2.f and a.l =  100 


Поясню почему. Как мне кажется такой вариант более эффективен
потому что в каждом select отсекаются лишние записи. При этом
нужно учесть что это простые запросы, а могут быть сложнее - там
где есть агрегатные функции, группировка, сортировка и т.п. в
каждом select входящем в union.

Вот и возникает вопрос будет ли сравним вариант 1) с вариантом 2)
по скорости выполнения если в объединении таблиц c_1,c_2 много
записей, но если наложить условие как описано выше после "внесения"
их в каждый select количество записей значительно уменьшается.

Поймет ли (оценит ли) это оптимизатор? Сможет ли сам сделать такое
преобразование?

Короче я сейчас проверяю. Просто думал может кто знает чисто
теоретически.
...
Рейтинг: 0 / 0
Подзапрос = обычная таблица в запросе?
    #32048958
Фотография toypaul
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Проверил. При наличии нужных индексов 1 вариант получился даже лучше! Теперь стоит подумать и проверить, что будет без индексов.

Честно говоря я удивлен таким возможностям оптимизатора. Я конечно подозревал, что так может быть (даже что должно), но, что так есть на самом деле...

з.ы. По плану запроса было видно, что он внес соответствующие условия внутрь select-ов тем самым резко ограничив объем обрабатывемой информации.
...
Рейтинг: 0 / 0
Подзапрос = обычная таблица в запросе?
    #32048982
соответсвующие условия внутрь оптимизатор переносит далеко не вегда и только для простых подзапросов.
...
Рейтинг: 0 / 0
Подзапрос = обычная таблица в запросе?
    #32048983
Фотография toypaul
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
соответсвующие условия внутрь оптимизатор переносит далеко не вегда и только для простых подзапросов.
А где можно про это почитать? Или может есть какие-то известные правила?
...
Рейтинг: 0 / 0
Подзапрос = обычная таблица в запросе?
    #32048985
Фотография toypaul
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Проверил еще на одном запросе. Вот два варианта:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
select a.schkod,sum(i.asum) from _1saccs a,
(
select accdtid aid,amount asum from _1sentry
union all
select accid aid,obdt1 asum from _1sbkttl
) i
where i.aid = a.id and left(a.schkod, 3 ) = ' 41'
group by a.schkod


Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
select schkod,sum(i.asum) from
(
select a.schkod,amount asum from _1saccs a,_1sentry i
where i.accdtid = a.id and left(a.schkod, 3 ) = ' 41'
union all
select a.schkod,obdt1 asum from _1saccs a,_1sbkttl i
where i.accid = a.id and left(a.schkod, 3 ) = ' 41'
) i
group by schkod


Здесь уже оптимизатор не переносит условия внутрь. Но всеравно разница во времени выполнения небольшая. Хотя второй вариант выполняется несколько быстрее.

Еще хотел бы спросить - как правильно производить сравнение скорости выполнения запросов. Во-первых чем? Во-вторых, что нужно сделать, чтобы были равные условия.

Как делаю сейчас. Первое - замеряю с помощью SQL Profiler по колонкам Start time, End time. Второе - перегружаю SQL Server. Правильно ли я поступаю?
...
Рейтинг: 0 / 0
9 сообщений из 9, страница 1 из 1
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Подзапрос = обычная таблица в запросе?
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]