loading..
Русский    English
18:07
листать

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

Рассмотрим простой пример, который генерирует последовательность Фибоначчи (в последовательности Фибоначчи каждый член равен сумме двух предыдущих, а первые 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

Bookmark and Share
Тэги:
ALL AND AUTO_INCREMENT AVG battles CASE CAST CHAR CHARINDEX CHECK classes COALESCE Convert COUNT CROSS APPLY CTE DATEDIFF DATENAME DATEPART DATETIME DDL DEFAULT DELETE DISTINCT DML EXCEPT EXISTS EXTRACT FROM FULL JOIN GROUP BY Guadalcanal HAVING IDENTITY IN INNER JOIN insert INTERSECT IS NOT NULL ISNULL laptop LEFT LEFT OUTER JOIN LEN maker MAX MIN MONTH MySQL NOT Больше тэгов
Учебник обновлялся
месяц назад
©SQL-EX,2008 [Развитие] [Связь] [О проекте] [Ссылки] [Team]
Перепечатка материалов сайта возможна только с разрешения автора.
Rambler's Top100