Вопрос
Начнем с небольшого вопроса. Что вернет такой запрос?select count(distinct [i]) [count] from ( select -30.0 / 5.0 / 3.0 / 2.0 / 1.0 [i] union select 30.0 /-5.0 / 3.0 / 2.0 / 1.0 union select 30.0 / 5.0 /-3.0 / 2.0 / 1.0 union select 30.0 / 5.0 / 3.0 /-2.0 / 1.0 union select 30.0 / 5.0 / 3.0 / 2.0 /-1.0 ) [Data]
Было бы неплохо, если бы он возвращал 1, но на самом деле ответом будет 3.
Копнем чуть глубже
Давайте посмотрим какие данные нам возвращаютсяselect 1 [index], -30.0 / 5.0 / 3.0 / 2.0 / 1.0 [i] union select 2, 30.0 /-5.0 / 3.0 / 2.0 / 1.0 union select 3, 30.0 / 5.0 /-3.0 / 2.0 / 1.0 union select 4, 30.0 / 5.0 / 3.0 /-2.0 / 1.0 union select 5, 30.0 / 5.0 / 3.0 / 2.0 /-1.0
Согласитесь, довольно неожиданный результат.
Давайте разберемся, что же такое происходит в строках 2 и 3 и почему строки 1,4 и 5 возвращают верные значения.
Согласно статье из msdn Приоритет операторов (Transact-SQL) следующий
- ~ (побитовое НЕ)
- * (умножение), / (деление), % (остаток от деления)
- + (положительное), - (отрицательное), + (сложение), (+ объединение), - (вычитание), & (побитовое И), ^ (побитовое исключающее ИЛИ), | (побитовое ИЛИ)
- =, >, <, >=, <=, <>, !=, !>, !< (операторы сравнения)
- NOT
- AND
- ALL, ANY, BETWEEN, IN, LIKE, OR, SOME
- = (присваивание)
Таким образом, исходный код можно представить в виде
select 1 [index], -(30.0 / 5.0 / 3.0 / 2.0 / 1.0) [i] union select 2, 30.0 /-(5.0 / 3.0 / 2.0 / 1.0) union select 3, 30.0 / 5.0 /-(3.0 / 2.0 / 1.0) union select 4, 30.0 / 5.0 / 3.0 /-(2.0 / 1.0) union select 5, 30.0 / 5.0 / 3.0 / 2.0 /-(1.0)
Теперь видно, что
- В строке № 1 сначала происходит деление, и лишь затем к результату применяется унарный минус.
- Строка № 4 возвращает верный ответ, только из-за удачно подобранных делителей.
- И лишь строка № 5 вычисляется так, как мы ожидаем.
круто, просек фишку )
ОтветитьУдалить