loading..
Русский    English
19:39
листать

Аналог рекурсии

Рассмотрим простой пример, который генерирует последовательность Фибоначчи (в последовательности Фибоначчи каждый член равен сумме двух предыдущих, а первые 2 равны единице):

  1. SELECT IF(X=1, Fn_1, Fn_2) F
  2. FROM(
  3.   SELECT @I := @I + @J Fn_1, @J := @I + @J Fn_2
  4.   FROM
  5.     (SELECT 0 dummy UNION ALL SELECT 0 UNION ALL SELECT 0)a,
  6.     (SELECT 0 dummy UNION ALL SELECT 0 UNION ALL SELECT 0)b,
  7.     (SELECT @I := 1, @J := 1)IJ
  8. )T,
  9.   /*Фиктивная таблица, для вывода последовательности в 1 столбец*/
  10.   (SELECT 1 X UNION ALL SELECT 2)X;

Данный запрос генерирует 18 чисел Фибоначчи, не считая первых двух:

F
2
3
5
8
13
21
34
55
89
144
233
377
610
987
1597
2584
4181
6765

Разберём теперь как оно работает.

В строчках 5) 6) генерируется 9 записей. Тут ничего необычного.

В строчке 7) мы объявляем две переменные @I, @J и присваиваем им 1.

В строке 3) происходит следующее: сначала переменной @I присваивается сумма двух переменных. Затем то же самое присваиваем переменной @J, причем с учетом того, что значение @I уже поменялось.

Другими словами, вычисления в SELECT выполняются слева направо – см. также замечание в начале статьи.

Причем изменение переменных осуществляется в каждой из наших 9 записей, т.е. при обработке каждой новой строки в переменных @I и @J будут содержаться значения, вычисленные при обработке предыдущей строки.

Чтобы решить эту же задачу средствами других СУБД, нам пришлось бы писать рекурсивный запрос!

Примечание:

Переменные нужно объявлять в отдельном подзапросе (строка 7), если бы мы объявили переменную в предложении SELECT, она, скорее всего, вычислилась бы только 1 раз (хотя конкретное поведение будет зависеть от версии сервера). Тип переменной определяется значением, которым она инициализирована. Этот тип может динамически меняться. Если переменной присвоить NULL, её типом будет BLOB.

Порядок обработки строк в SELECT, как было сказано выше, зависит от пользовательской сортировки. Простой пример нумерации строк в заданном порядке:

  1. SELECT val, @I:=@I+1 Num
  2. FROM
  3.   (SELECT 30 val UNION ALL SELECT 20 UNION ALL SELECT 10 UNION ALL SELECT 50)a,
  4.   (SELECT @I := 0)I
  5. ORDER BY val;

Val Num
10 1
20 2
30 3
50 4

Тэги:
ALL AND AUTO_INCREMENT AVG battles CASE CAST CHAR CHARINDEX CHECK classes COALESCE CONSTRAINT Convert COUNT CROSS APPLY CTE DATEADD DATEDIFF DATENAME DATEPART DATETIME DDL DEFAULT DELETE DISTINCT DML EXCEPT EXISTS EXTRACT FOREIGN KEY FROM FULL JOIN GROUP BY Guadalcanal HAVING IDENTITY IN INFORMATION_SCHEMA INNER JOIN insert INTERSECT IS NOT NULL IS NULL ISNULL laptop LEFT LEFT OUTER JOIN LEN maker Больше тэгов
Учебник обновлялся
несколько дней назад
https://exchangesumo.com/obmen/XMR-ZEC/
©SQL-EX,2008 [Развитие] [Связь] [О проекте] [Ссылки] [Team]
Перепечатка материалов сайта возможна только с разрешения автора.