Отправляет email-рассылки с помощью сервиса Sendsay
  Все выпуски  

Новости сайта "Упражнения по SQL" (http://www.sql-ex.ru) 235


Новости сайта "Упражнения по SQL (http://www.sql-ex.ru)"

Выпуск 235 от 28 марта 2009 г.

Новым посетителям сайта

SQL Exercises Сайт посвящен изучению языка, с помощью которого осуществляется взаимодействие с реляционными (и не только) СУБД. Суть обучения состоит в выполнении заданий на написание запросов к учебным базам данных; при этом система контролирует правильность выполнения заданий. В настоящее время реализованы все операторы подъязыка манипуляции данными (DML), которые включают в себя оператор извлечения данных SELECT, а также операторы модификации данных - INSERT, DELETE и UPDATE.

Мы надеемся, что справочного материала сайта окажется достаточно для самостоятельного обучения. Кроме того, свои решения вы можете обсудить на форуме сайта. Опытных же специалистов приглашаем проверить (продемонстрировать) свое мастерство и принять участие в соревновании, обеспечиваемом рейтинговой системой учета времени выполнения заданий. Фактически, рейтинг ведется на втором этапе тестирования, который начинается сейчас после решения 50-й задачи первого этапа. При подсчете рейтинга каждого участника отбрасывается один самый худший показатель среди всех решенных им упражнений.

Демонстрация плана выполнения запроса и сравнительная оценка эффективности решений поможет вам освоить принципы оптимизации запросов, которые пригодятся на третьем рейтинговом этапе, который начинается после 138 задачи.

Имеется возможность получить сертификат по SQL DML при выполнении определенного количества заданий.


Новости сайта

§ По многочисленным просьбам фактическое время выполнения авторского и тестового решения выводится также и при правильном решении задачи (второй/третий рейтинговые этапы задач на SELECT).

§ Принял английский вариант формулировки рейтинговой задачи 83, который любезно предложил BW.
Исправил также неточность в английской формулировке задачи 31 (обучающий этап), на которую обратил внимание petrus.

§ Оказалось, что оптимизатор для некоторых запросов показывает такую стоимость, для которой не хватало 12 знаков для отображения на странице рейтинга по стоимости. На этот казус обратил внимание _Bkmz_. Увеличил до 15 знаков. Если оценка стоимости превысит и этот размер, то на странице будут выводиться звездочки ("*").

§ Компенсировал время простоя с 26-03-2009 по 27-03-2009.

§ Изменения среди лидеров (решенные за неделю задачи третьего этапа):
Смена лидера!
1. Arcan (154)
3. $erges (153)
6. Ozzy (150)
8. Umrikhina (149, 150)
9 anddros (152)
37. SCAT (140, 142)

§ Продвинулись в рейтинге:
50. _Bkmz_ (137, 5.933)

§ Продвижение ближайших претендентов на попадание в ТОР 100:
156. Galogen (112, 99.947)
161. AlexPhil (115, 5.001)
243. Avtolic (243, 11.248)

§ На этой неделе сертифицированы:
Wiedzmen (A09046536) [BK] - г.Киев, Украина
PavelF (A09035666) [BK] - г.Москва, Россия
yorcky (A09046040) [BK] - г.Астрахань, Россия
juan (A09009184) [BK] - г.Люберцы, МО, Россия

§ Число подписчиков - 3835

Число участников рейтинга - 19772

Число участников второго этапа - 1755

Число участников третьего этапа - 47

Сертифицировано на сайте - 363

Лучшие результаты (ТОР 20)

No Person Number of
Sel_ex
Last_Sel Number of
DML_ex
Scores Days Days_2 Days_3 S_3 LastSolved LastVisit
1 Креславский О.М. (Arcan)1 154 154 21 376 782 65.266 46.391 53 22 Mar 2009 27 Mar 2009
2 Карасёва Н.В. (vlksm)1 154 154 21 376 1049 90.124 61.061 53 20 Mar 2009 26 Mar 2009
3 Сальников С.А. ($erges)1 153 153 21 372 392 3.854 4.191 49 24 Mar 2009 27 Mar 2009
4 Сенкевич С.В. (GreyC)1 152 152 21 369 358 57.860 27.102 46 26 Jan 2009 27 Mar 2009
5 Селезнёв А.С. (Артём С.)1 150 152 21 363 444 47.248 37.524 46 25 Jan 2009 03 Mar 2009
6 >Зотов П.Г. (Ozzy)6 146 150 21 353 382 131.526 149.241 43 27 Mar 2009 27 Mar 2009
7 Никотин В.М. (@Nikotin)1 150 150 21 363 108 8.371 3.751 40 13 Dec 2008 27 Mar 2009
8 >Умрихина Е.В. (Umrikhina)8 150 150 21 363 337 20.856 23.215 40 27 Mar 2009 27 Mar 2009
9 Дроздков А.Н. (anddros)8 149 152 21 361 303 6.162 6.811 38 26 Mar 2009 27 Mar 2009
10 Печатнов В.В. (pvv)1 146 149 21 350 357 30.849 17.490 36 10 Oct 2008 25 Mar 2009
11 Муллаханов Р.Х. (rem)9 149 152 21 358 483 14.427 20.056 35 05 Jan 2009 25 Mar 2009
12 Мурашкин И.В. (lepton)1 143 152 21 343 1059 68.477 57.992 33 14 Feb 2009 15 Feb 2009
13 Шиндин А.В. (AlShin)10 147 150 21 353 79 20.458 7.203 30 05 Jan 2009 28 Jan 2009
14 Держальцев В.А. (MadVet)7 137 146 21 331 1257 60.783 28.482 28 24 Sep 2008 30 Dec 2008
15 Любченко В.А. (IAS56)6 136 146 21 330 615 403.343 373.617 28 11 May 2008 01 Dec 2008
16 Голубин Р.С. (Roman S. Golubin)3 141 145 21 336 1260 93.162 58.822 25 29 Jan 2009 08 Feb 2009
17 Nikolaenko A.V. (Shadow77)12 142 147 21 337 436 77.451 14.010 23 22 Oct 2008 11 Dec 2008
18 Солдатенков Ю.С. (SolYUtor)2 138 146 21 329 819 22.615 6.102 20 14 Aug 2008 18 Mar 2009
19 Белогурова К. (Katy_Ekb)19 133 143 21 319 552 10.666 4.673 18 27 Nov 2008 18 Jan 2009
20 Егоров А.Б. (ABEgorov)20 137 144 21 327 180 12.897 8.815 18 03 Aug 2008 12 Aug 2008

Лучшие результаты за неделю

No surname n_sel sel_all sel_scores dml_scores scores rating last_visit
1 Сафонов К.А. (safonov) 38 49 81 19 100 1355 27 Mar 2009
2 >Szen K. (occulta) 40 40 73 3 76 2643 27 Mar 2009
3 Соколов О.Н. (notemp) 32 42 68 0 68 2478 24 Mar 2009
4 Гайнанова (Stud_Maryam) 33 33 65 0 65 3430 25 Mar 2009
5 Puzo P.P. (puzo) 27 33 60 0 60 2226 24 Mar 2009
6 >Михайлова (Nickolas) 25 39 56 0 56 2719 27 Mar 2009
7 >Аноним (WereWolf777) 30 30 56 0 56 4240 27 Mar 2009
8 >Усик В.Н. (Vladius) 24 36 55 0 55 3229 27 Mar 2009
9 Nurgaliev A. (Albert109) 25 32 54 0 54 3820 25 Mar 2009
10 >Радин П.Л. (vinchenzo) 27 27 48 3 51 4763 27 Mar 2009
11 Сафронова (Miss Hamster) 22 40 50 0 50 1709 26 Mar 2009
12 Фамилия (qwe123) 26 26 47 0 47 5241 26 Mar 2009
13 >Тараканова Е. (yar_stranger) 15 26 36 9 45 4178 27 Mar 2009
14 Волкова К. (cappuccino) 18 28 42 3 45 4271 26 Mar 2009
15 Захарченко А.С. (zaharchenko) 25 25 45 0 45 5501 25 Mar 2009
16 Данила С.В. (QWERiON) 17 29 34 9 43 4303 25 Mar 2009
17 >Цикалюк В.В. (exroot) 17 38 36 0 36 2722 27 Mar 2009
18 Быховой А.Н. (Андрей_спец) 16 24 36 0 36 5621 27 Mar 2009
19 >Фрис А.Р. (ARF) 3 52 3 32 35 999 27 Mar 2009
20 >Vashkevich N.I. (Natasha_Vashkevich) 20 68 33 0 33 595 27 Mar 2009
21 Ильин (Nike6) 21 64 33 0 33 1300 26 Mar 2009
22 >Киршанский С.П. (kirser) 21 21 33 0 33 6997 27 Mar 2009
23 Ssp (Baumanec) 14 23 32 0 32 5993 27 Mar 2009
24 >Малых А.С. (casta-1988) 16 16 23 9 32 7093 27 Mar 2009
25 Дроздов А.А. (aledro) 20 20 32 0 32 7106 24 Mar 2009
26 >Машарова-Григорець Г. (Galina_MG) 20 20 32 0 32 7127 27 Mar 2009
27 >Фотина Е.Ю. (katerina80) 13 24 31 0 31 5837 27 Mar 2009
28 >Antanevich Y. (Avtolic) 11 114 30 0 30 243 27 Mar 2009
29 Титкин А.А. (Creol) 15 88 30 0 30 308 27 Mar 2009
30 >Кескинов М.В. (Михаил Кескинов) 13 24 30 0 30 5958 27 Mar 2009

Изучаем SQL

Массивы и списки в SQL Server 2005 (начало в вып.217-229, 231-234)

Erland Sommarskog (оригинал: Arrays and Lists in SQL Server 2005 )
Перевод: Моисеенко С.И.

Использование рекурсивных CTE

Это метод, который является совершенно новым для SQL 2005. Этот метод первоначально предложил мне SQL Server MVP Найджел Риветт (Nigel Rivett). Функция, основанная на этой идее, также опубликована в книге SQL Server MVP Ицика Бен-Гана (Itzik Ben-Gan) Inside SQL Server 2005: T-SQL Querying (SQL Server 2005 изнутри: Написание запросов в T-SQL).

Этот метод не входит в число самых быстрых; он превосходит итерационный метод всего лишь на 15 %. Однако, Найджел Риветт предпочитает этот метод, потому что, говорит он, работая в качестве консультанта, пытается оставить по возможности небольшой след, предпочтительно, даже не функцию. И действительно, метод CTE довольно удобно использовать непосредственно в хранимой процедуре. Тем не менее, я покажу метод, упакованный во встраиваемую функцию:

CREATE FUNCTION cte_split_inline (@list  nvarchar(MAX),
                                  @delim nchar(1) = ',') RETURNS TABLE AS
RETURN
   WITH csvtbl(start, stop) AS (
     SELECT start = convert(bigint, 1),
            stop = charindex(@delim COLLATE Slovenian_BIN2, @list + @delim)
     UNION ALL
     SELECT start = stop + 1,
            stop = charindex(@delim COLLATE Slovenian_BIN2,
                             @list + @delim, stop + 1)
     FROM   csvtbl
     WHERE  stop > 0
  )
  SELECT ltrim(rtrim(substring(@list, start,
                      CASE WHEN stop > 0 THEN stop - start ELSE 0 END)))
         AS Value
  FROM   csvtbl
  WHERE  stop > 0
go

То, что начинается с WITH, и есть Общее Табличное Выражение (Common Table Expression - CTE). Простой CTE подобен макросу, который Вы определяете перед запросом, и который затем Вы можете использовать в запросе так, как будто это таблица. Немного более причудливая производная таблица, если угодно. Но CTE приведенный выше - есть специальная форма CTE, а именно, рекурсивный CTE. Рекурсивный CTE, состоит из двух операторов SELECT, объединяемых при помощи оператора UNION ALL. Первый оператор SELECT - это начальная точка. Второй оператор SELECT делает ссылку на сам CTE. Структуру можно представить в виде длинного списка:

SELECT ...
UNION ALL
SELECT ...
FROM   CTE
UNION ALL
SELECT ...
FROM   CTE
 ...

где каждый оператор SELECT имеет на входе CTE из оператора SELECT, расположенного непосредственно выше. Рекурсия продолжается, пока операторы SELECT продолжают производить новые строки. Окончательный результат UNION ALL всех операторов SELECT. (Этот рекурсивный запрос является несколько необычным, так как он не ссылается ни на какие таблицы. Обычно Вы используете рекурсивный CTE, чтобы раскрутить инвентарные списки и другие иерархические структуры).

Итак, в этой функции, первый SELECT возвращает 1, c которой начинается список, и положение первого разделителя. Второй SELECT устанавливает start в положение после первого разделителя и stop - в положение второго разделителя. Третий SELECT, что подразумевается рекурсией, возвращает положение после второго разделителя как начальное положение и положение для третьего разделителя. Это продолжается до тех пор, пока не закончатся разделители, и значение stop не станет равным 0; при этом последний оператор SELECT не возвращает вообще ничего.

Все это создает виртуальную таблицу, содержащую начальную и конечную позиции для всех элементов списка, и мы можем использовать строки в этой таблице в качестве входных значений для substring в сочетании со специальной обработкой последнего элемента списка.

Ниже приведен пример использования этой функции:

CREATE PROCEDURE get_company_names_cte @customers nvarchar(2000) AS
   SELECT C.CustomerID, C.CompanyName
   FROM   Northwind..Customers C
   JOIN   cte_split_inline(@customers, ',') s ON C.CustomerID = s.Value
   OPTION (MAXRECURSION 0)
go
EXEC get_company_names_cte 'ALFKI, BONAP, CACTU, FRANK'

Обратите внимание на предложение OPTION. Без этого предложения SQL Server прервал бы выполнение функции преждевременно, если в списке содержится более 100 элементов, т.к. 100 - это значение по умолчанию для MAXRECURSION (максимальное число итераций). MAXRECURSION служит защитой от бесконечно выполняющихся рекурсий. Для "более нормального" использования CTE, например, для отношений предприниматель-менеджер, 100 - это много, но в нашем случае 100 - слишком маленькое число. Поэтому мы устанавливаем MAXRECURSION в значение 0, которое полностью отключает проверку числа итераций.

Но почему предложение OPTION не поместить внутрь функции? Только по той причине, что использование предложений OPTION запрещено во встраиваемых функциях. Вспомним, что встраиваемые функции фактически функциями не являются, это лишь макроопределения, которые вставляются в вызывающий их запрос.

Функция не возвращает позицию в списке, но можно легко это сделать, добавив столбец счетчика к CTE:

SELECT ..., listpos = 1
 ...
UNION ALL
SELECT ..., listpos = listpos + 1

Как Вы можете догадаться, эта функция теряет в производительности из-за комбинации nvarchar (MAX) и charindex. К ней можно обратиться, написав многооператорную функцию, которая разбивает входной список на куски в манере, подобной duo_chunk_split_me. Однако мои тесты показали, что избыточные затраты на распределение данных по возвращаемой таблице в многооператорной функции несколько превосходят стоимость для charindex на nvarchar(MAX). Непритязательность метода CTE делает функцию разбиения на куски менее привлекательной, и я оставляю в качестве упражнения читателю ее реализацию. Или посмотрите ссылку.

Процедуры, которые используют cte_split_inline, подвержены проблеме кэширования, обсуждаемой мной ранее, поэтому предпочтительней возможно будет скопировать входной параметр в локальную переменную.

(Продолжение следует...)

Полезная информация

§ Приглашаем вас посетить новый проект - Интерактивный учебник по SQL.
   Ресурс позиционируется как "справочное обеспечение" для сайта SQL-EX.RU, но может использоваться и независимо от него.

§ Онлайновый выпуск рассылки можно почитать на сайте.

§ Все статьи, публикуемые в рассылке, затем выкладываются на сайте Книги и статьи по SQL.

§ Хотите поддержать проект? Вот инструкция по применению. :-)

Контакты

По всем вопросам, связанным с функционированием сайта, проблемами при решении упражнений, идеями вы можете обращаться к Сергею И.Моисеенко msi77[@]yandex.ru. Вы также можете предложить свои задачи для публикации на сайте.

Подписка Subscribe.Ru
Новости сайта "Упражнения по SQL"

В избранное