Добрый день, коллеги!
Продолжая начатую тему
[SQL Server] Головоломки (Часть 1), решил опубликовать еще пять вопросов...
1. order by (select null)
Дано: Запрос вида
select * from dbo.Table1 order by (select null)
Вопрос: Можно ли с какой-то долей уверенности сказать будут ли отсортированы данные и в каком порядке?
a) Да
б) Нет
| Ответ |
| б) Нет
Подсказка:
Правильный ответ – Нет. Предложение order by (select null) будет проигнорировано при выполнении, т.е. данные вернутся в произвольном порядке, как если бы указание сортировки отсутствовало. Конструкция применяется там, где является обязательным использование последовательности данных, но по каким-то причинам поле или набор полей упорядочения не может быть определен, например аналитические функции row_number() over(order by (select null)) или использование паджинации order by (select null) offset 10 rows fetch next 5 rows only.
|
| |
2. Декартово произведение
Дано: Три запроса
/* 1 */
select *
from dbo.Table1 t1
cross join dbo.Table2 t2
/* 2 */
select *
from dbo.Table1 t1, dbo.Table2 t2
/* 3 */
select *
from dbo.Table1 t1
join dbo.Table2 t2 on 1 = 1
Вопрос: Какие из представленных выше запросов реализуют декартово произведение?
a) Все
б) 1, 2
в) 2, 3
г) 1, 3
д) Ни один
Выберите один вариант ответа
| Ответ |
| a) Все
Подсказка:
Все 3-и запроса реализуют декартово произведение —
Запрос 1 использует стандарт ANSI-92
Запрос 2 использует стандарт ANSI-89
Запрос 3 использует INNER JOIN с «липовым» условием соединения 1 = 1
|
| |
3. Приоритет типов данных в предикатах соединения
Дано: Две пустые таблицы
create table dbo.Test1
(
StringColumn varchar(20)
)
create table dbo.Test2
(
NumericColumn numeric(19, 0),
DateTimeColumn datetime
)
и два запроса соединяющие таблицы по полям разных типов. Запросы выполняются по отдельности.
/* 1 */
select *
from dbo.Test1 t1
join dbo.Test2 t2 on t1.StringColumn = t2.NumericColumn
/* 2 */
select *
from dbo.Test1 t1
join dbo.Test2 t2 on t1.StringColumn = t2.DateTimeColumn
Вопрос: К какому типу данных будут преобразованы столбцы, используемые в условии соединения таблиц?
a) В запросе 1 столбец t1.StringColumn участвующий в связывании таблиц будет преобразован к типу numeric(19, 0)
б) В запросе 1 столбец t2.NumericColumn участвующий в связывании таблиц будет преобразован к типу varchar(20)
в) При выполнении запроса 1 возникнет ошибка
г) В запросе 2 столбец t1.StringColumn участвующий в связывании таблиц будет преобразован к типу datetime
д) В запросе 2 столбец t2.DateTimeColumn участвующий в связывании таблиц будет преобразован к типу varchar(20)
е) При выполнении запроса 2 возникнет ошибка
Выберите два варианта ответа
| Ответ |
| a) В запросе 1 столбец t1.StringColumn участвующий в связывании таблиц будет преобразован к типу numeric(19)
г) В запросе 2 столбец t1.StringColumn участвующий в связывании таблиц будет преобразован к типу datetime
Подсказка:
Столбцы, используемые в условии соединения, не обязательно должны иметь одинаковые имена или одинаковый тип данных. Однако если типы данных не совпадают, то они должны быть совместимыми или допускать в SQL Server неявное преобразование. При выполнении неявного преобразования используется старшинство типов данных согласно документу Data Type Precedence (Transact-SQL) Из 3-х типов данных представленных в запросах выше varchar имеет низший приоритет, поэтому столбцы участвующие в соединениях будут преобразованы к типам данных с более высоким приоритетом — numeric и datetime.
|
| |
4. Объявление переменных
Дано: Запрос, который заполняет в цикле табличную переменную
declare @i int = 0
while (@i < 10)
begin
declare @table table(i int)
insert into @table select @i
set @i += 1
end
select * from @table
Вопрос: Какие данные будут содержаться в переменной @table после выполнения цикла?
a) При выполнении возникнет ошибка «The variable name '@table' has already been declared»
б) Таблица будет содержать 0 записей
в) Таблица будет содержать 1 запись со значением 9
г) Таблица будет содержать 10 записей со значениями от 0 до 9
| Ответ |
| г) Таблица будет содержать 10 записей со значениями от 0 до 9
Подсказка:
Все переменные, в том числе и табличные, создаются предварительно, т.е. на этапе компиляции запроса. Именно поэтому во время выполнения цикла будет использоваться единственный экземпляр переменной @table, в который попадут 10 записей от 0 до 9.
|
| |
5. select @local_variable и несколько значений
Дано: Таблица, содержащая 4 записи и запрос, который инициализирует переменную через оператор select.
select *
into #temp
from (values (1),(3),(4),(2)) t(k)
declare @i int
select @i = k from #temp order by k
select @i
Вопрос: Чему равно значение переменной @i после выполнения запроса?
a) 1
б) 2
в) 3
г) 4
д) NULL
| Ответ |
| г) 4
Подсказка:
Согласно документации SELECT @local_variable (Transact-SQL) обычно используется для возвращения одиночного значения в переменную. Однако, если аргумент expression является именем столбца, может вернуться несколько значений. Если инструкция SELECT возвращает более одного значения, переменной присваивается последнее возвращенное значение.
|
| |
Здравствуйте, Olaf, Вы писали:
O>Добрый день, коллеги!
O>Продолжая начатую тему [SQL Server] Головоломки (Часть 1), решил опубликовать еще пять вопросов...
Наткнулся вот на еще один аспект потенциально интересный.
union
Дано: Два непересекающихся набора данных и запрос вида:
declare @ds1 table (id int, amount money)
declare @ds2 table (id int, amount money)
insert into @ds1 (id, amount) values (2, 200), (3, 300)
insert into @ds2 (id, amount) values (1, 100), (1,100)
select
id
, totalAmount = sum(amount)
from (select id, amount from @ds1 union
select id, amount from @ds2) t
where id = 1
group by id
Вопрос: что вернет запрос?
| Ответ |
| 100, т.к. union удаляет все дубликаты, включая те, что содержатся внутри одного и того же результата запроса. |
| |