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

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


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

Выпуск 224 от 10 января 2009 г.

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

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

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

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

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


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

§ На третий этап выставлена новая задача от vlksm - 152 (сложность 3 балла).

§ Исполнил пожелание о добавлении столбца с баллами по голосованию в рейтинг задач второго этапа.

§ Изменения среди лидеров (решенные за неделю задачи третьего этапа):
1. Arcan (151, 152)
2. vlksm (151, 152)
6. GreyC (148)
8. rem (152)
9. AlShin (148, 150)

§ Продвинулись в рейтинге:
50. Angellore (задач 135, время 155.722)

§ Продвижение ближайших претендентов на попадание в ТОР 100:
116. lambda (121, 45.524)
122. Cергей L (120, 51.762)
182. vitaliiS (110, 88.341)

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

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

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

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

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

Лучшие результаты (ТОР 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) 152 152 21 370 707 59.893 41.017 46 06 Jan 2009 09 Jan 2009
2 Карасёва Н.В. (vlksm) 152 152 21 370 975 79.787 50.723 46 05 Jan 2009 09 Jan 2009
3 Никотин В.М. (@Nikotin) 150 150 21 364 108 8.371 3.751 40 13 Dec 2008 09 Jan 2009
4 Сальников С.А. ($erges) 150 150 21 364 291 3.487 3.824 40 13 Dec 2008 31 Dec 2008
5 Печатнов В.В. (pvv) 146 149 21 352 357 30.849 17.490 36 10 Oct 2008 09 Jan 2009
6 Сенкевич С.В. (GreyC) 149 148 21 360 338 50.039 19.282 36 06 Jan 2009 09 Jan 2009
7 Селезнёв А.С. (Артём С.) 145 149 21 349 322 38.500 29.235 36 25 Sep 2008 21 Nov 2008
8 Муллаханов Р.Х. (rem) 149 152 21 359 483 14.427 20.056 35 05 Jan 2009 09 Jan 2009
9 Шиндин А.В. (AlShin) 147 148 21 354 79 20.458 7.203 30 05 Jan 2009 07 Jan 2009
10 Мурашкин И.В. (lepton) 142 150 21 342 995 47.797 37.312 30 12 Dec 2008 18 Dec 2008
11 Держальцев В.А. (MadVet) 137 146 21 333 1257 60.783 28.482 28 24 Sep 2008 30 Dec 2008
12 Зотов П.Г. (Ozzy) 141 146 21 340 264 61.111 78.826 28 29 Nov 2008 09 Jan 2009
13 Любченко В.А. (IAS56) 136 146 21 332 615 403.343 373.617 28 11 May 2008 01 Dec 2008
14 Голубин Р.С. (Roman S. Golubin) 140 145 21 335 1122 93.042 58.822 25 13 Sep 2008 06 Dec 2008
15 Дроздков А.Н. (anddros) 145 151 21 348 217 4.593 1.153 24 30 Dec 2008 06 Jan 2009
16 Nikolaenko A.V. (Shadow77) 142 147 21 339 436 77.451 14.010 23 22 Oct 2008 11 Dec 2008
17 Солдатенков Ю.С. (SolYUtor) 138 146 21 331 819 22.615 6.102 20 14 Aug 2008 23 Oct 2008
18 Белогурова К. (Katy_Ekb) 133 143 21 321 552 10.666 4.673 18 27 Nov 2008 09 Dec 2008
19 Егоров А.Б. (ABEgorov) 137 144 21 329 180 12.897 8.815 18 03 Aug 2008 12 Aug 2008
20 Войнов П.Е. (pаparome) 139 146 21 330 1125 3.124 .213 17 22 Sep 2008 11 Dec 2008

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

No surname n_sel sel_all sel_scores dml_scores scores rating last_visit
1 >G. M. (amg__) 49 62 93 34 127 775 09 Jan 2009
2 >Борисок В.В. (Barysok Valery) 58 71 118 0 118 932 09 Jan 2009
3 >Евдокимова И.А. (ilebedeva) 38 38 71 0 71 2884 09 Jan 2009
4 >voba (nancy-v) 36 36 68 0 68 3082 08 Jan 2009
5 >Гуров А.Ю. (Tokio3) 31 31 58 7 65 3299 09 Jan 2009
6 >Олонцев С.А. (TORCH) 36 68 64 0 64 574 08 Jan 2009
7 Степанов И.Н. (Mozgofil) 26 40 59 0 59 2567 05 Jan 2009
8 >Козлов А.А. (Андрей Козлов) 25 38 56 0 56 2896 09 Jan 2009
9 Мурсалова И.А. (Irina17) 15 25 35 9 44 4222 06 Jan 2009
10 Hysenaj E. (SQL_Endri) 24 24 43 0 43 5505 07 Jan 2009
11 >Шелудько В.В. (Bитеk) 18 67 30 11 41 595 09 Jan 2009
12 >aaaa (Регул) 24 34 39 0 39 2172 09 Jan 2009
13 Piquero M.A. (Tekloh) 17 25 39 0 39 5077 08 Jan 2009
14 >Колосок А.В. (scythian) 26 26 38 0 38 6127 09 Jan 2009
15 kapur (Vikaskapur) 17 17 26 9 35 6426 09 Jan 2009
16 >Крылов С.А. (Serg71) 14 41 34 0 34 2492 09 Jan 2009
17 magos F.T. (magz) 19 19 29 0 29 7425 08 Jan 2009
18 >Поварницын А.В. (Respectable) 19 19 28 0 28 7723 09 Jan 2009
19 Ларина О.В. (_olga_) 12 49 21 4 25 1703 08 Jan 2009
20 zilberman (oziman) 12 40 25 0 25 2493 09 Jan 2009
21 >Rakovich A. (Lohmatyi) 18 18 23 0 23 8787 09 Jan 2009
22 Свирин П.В. (Hellcat) 0 48 0 21 21 1208 09 Jan 2009
23 Shabanov V. (vadym_sh) 10 18 21 0 21 7569 05 Jan 2009
24 >Сенькин В.Н. (vitaliiS) 7 110 20 0 20 182 09 Jan 2009

Изучаем SQL

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

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

Список целых чисел

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

CREATE FUNCTION iter$simple_intlist_to_tbl (@list nvarchar(MAX))
   RETURNS @tbl TABLE (number int NOT NULL) AS
BEGIN
   DECLARE @pos        int,
           @nextpos    int,
           @valuelen   int

   SELECT @pos = 0, @nextpos = 1

   WHILE @nextpos > 0
   BEGIN
      SELECT @nextpos = charindex(',', @list, @pos + 1)
      SELECT @valuelen = CASE WHEN @nextpos > 0
                              THEN @nextpos
                              ELSE len(@list) + 1
                         END - @pos - 1
      INSERT @tbl (number)
         VALUES (convert(int, substring(@list, @pos + 1, @valuelen)))
      SELECT @pos = @nextpos
   END
  RETURN
END

Идея проста. Мы в цикле проходим по строке, находя запятую, и затем извлекаем значения между запятыми. Обратите внимание на использование третьего параметра в charindex, он определяет позицию, откуда начинается поиск следующей запятой. Лишь вычисление @valuelen представляет единственную сложность: мы должны обработать тот факт, что charindex возвратит 0, когда запятые в списке заканчиваются.

Однако, эта функция медленнее, чем следовало бы. Когда я писал ту же самую функцию на SQL 2000 несколько лет назад, мне пришлось применить технику разбиения входной строки на куски. Это было необходимо, потому что в SQL 2000 нет типа nvarchar (MAX), лишь только ntext, а charindex работает только в пределах первых 8000 байтов для значения типа ntext. Я надеялся, что с nvarchar(MAX) разбиение на куски не потребуется, но испытание показало, что при использовании кусков по nvarchar (4000) я смог улучшить производительность на 20-30 %. Дело было в charindex: эта функция работает на nvarchar(MAX) медленнее, чем на nvarchar(4000). Почему я не знаю, но поскольку размер значений nvarchar (MAX) может достигать 2 ГИГАБИТОВ, я предполагаю, что charindex имеет более сложную реализацию в случае nvarchar(MAX).

Есть вторая проблема с iter$simple_intlist_to_tbl: если Вы по некоторым причинам передадите в нее две последовательных запятые, она даст вам 0 на выходе, что не очень хорошо. Хотя Вы можете легко избежать этой проблемы, добавив немного логики в функцию, но я предпочитаю обойти эту проблему при помощи использования пробела в качестве разделителя. Запятая действительно не имеет никакого смысла для списка целых чисел.

Итак, вот лучшая реализация итерационного метода для списка целых чисел:

CREATE FUNCTION iter_intlist_to_tbl (@list nvarchar(MAX))
   RETURNS @tbl TABLE (listpos int IDENTITY(1, 1) NOT NULL,
                       number  int NOT NULL) AS
BEGIN
   DECLARE @startpos int,
           @endpos   int,
           @textpos  int,
           @chunklen smallint,
           @str      nvarchar(4000),
           @tmpstr   nvarchar(4000),
           @leftover nvarchar(4000)

   SET @textpos = 1
   SET @leftover = ''
   WHILE @textpos <= datalength(@list) / 2
   BEGIN
      SET @chunklen = 4000 - datalength(@leftover) / 2
      SET @tmpstr = ltrim(@leftover +
                    substring(@list, @textpos, @chunklen))
      SET @textpos = @textpos + @chunklen

      SET @startpos = 0
      SET @endpos = charindex(' ' COLLATE Slovenian_BIN2, @tmpstr)

      WHILE @endpos > 0
      BEGIN
         SET @str = substring(@tmpstr, @startpos + 1,
                              @endpos - @startpos - 1)
         IF @str <> ''
            INSERT @tbl (number) VALUES(convert(int, @str))
         SET @startpos = @endpos
         SET @endpos = charindex(' ' COLLATE Slovenian_BIN2,
                                 @tmpstr, @startpos + 1)
      END

      SET @leftover = right(@tmpstr, datalength(@tmpstr) / 2 - @startpos)
   END

   IF ltrim(rtrim(@leftover)) <> ''
      INSERT @tbl (number) VALUES(convert(int, @leftover))

   RETURN
END

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

CREATE PROCEDURE get_product_names_iter @ids varchar(50) AS
   SELECT P.ProductName, P.ProductID
   FROM   Northwind..Products P
   JOIN   iter_intlist_to_tbl(@ids) i ON P.ProductID = i.number
go
EXEC get_product_names_iter '9 12 27 37'

Эта функция содержит два цикла. Один из них создает куски, а второй проходит по этим кускам. Первый кусок всегда 4000 символов (при условии, что на вход подаются не менее длинные строки). Поскольку мы проходим в конец куска, то, вероятно, будем находиться в середине элемента, который мы сохраняем в @leftover. Мы переносим @leftover на следующий кусок, и поэтому теперь мы можем захватить меньше, чем 4000 символов из @list. Когда мы переходим к последнему куску, @leftover просто является последним элементом списка.

Многократные пробелы обрабатываются простым игнорированием @str, если она содержит пробел.

Есть две момента, обсуждаемых в "Общих соображениях", которые использую в этой функции, и которых не было в iter$simple:
- выходная таблица включает позицию в списке.
- я использую предложение COLLATE для приведения к бинарной коллации, чтобы получить еще некоторый выигрыш в производительности.

Мне также хочется отметить небольшой прирост производительности по сравнению с версией, которую я приводил в статье для SQL 2000. Сэм Саффрон (Sam Saffron ) указал мне, что я сохраняю перераспределенную строку вместо того, чтобы использовать третий параметр функции charindex.

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

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

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

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

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

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

Контакты

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

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

В избранное