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

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


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

Выпуск 229 от 14 февраля 2009 г.

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

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

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

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

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


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

§ Усилил проверку задачи 32 (рейтинговый этап) в ответ на сообщение nonStyle.

§ Fiolent добавил подсказку для задачи 103. Также появилась подсказка для задачи 65.

§ Fantast обратил внимание на то, что комбинация "ctrl+enter" не работает на упражнениях DML (как, впрочем, и на обучающем этапе). Исправил.

§ Под номером 153 выставлена новая задача от Ozzy (сложность 3 балла).
Первое место вакантно. :-)

§ Изменения среди лидеров (решенные за неделю задачи третьего этапа):
10. anddros (146)
13. Umrikhina (146)
42. AKudrakov (139, 142)

§ Новые лица в ТОР 100 и вернувшиеся туда:
95. ValdemarES (задач 122, время 18.445)

§ Продвижение ближайших претендентов на попадание в ТОР 100:
104. a66at (124, 4.735)
126. B o r i s (120, 127.568)
186. _irina_ (110, 24.763)

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

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

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

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

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

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

No Person Number of
Sel_ex
Last_Sel Number of
DML_ex
Scores Days Days_2 Days_3 S_3 LastSolved LastVisit
1 Сенкевич С.В. (GreyC) 152 152 21 371 358 57.860 27.102 46 26 Jan 2009 13 Feb 2009
2 Селезнёв А.С. (Артём С.) 150 152 21 365 444 47.248 37.524 46 25 Jan 2009 10 Feb 2009
3 Креславский О.М. (Arcan) 152 152 21 371 707 59.893 41.017 46 06 Jan 2009 13 Feb 2009
4 Карасёва Н.В. (vlksm) 152 152 21 371 975 79.787 50.723 46 05 Jan 2009 13 Feb 2009
5 Сальников С.А. ($erges) 151 152 21 368 346 3.578 3.915 43 06 Feb 2009 13 Feb 2009
6 Никотин В.М. (@Nikotin) 150 150 21 365 108 8.371 3.751 40 13 Dec 2008 13 Feb 2009
7 Печатнов В.В. (pvv) 146 149 21 352 357 30.849 17.490 36 10 Oct 2008 13 Feb 2009
8 Муллаханов Р.Х. (rem) 149 152 21 360 483 14.427 20.056 35 05 Jan 2009 13 Feb 2009
9 Зотов П.Г. (Ozzy) 143 148 21 345 332 93.532 111.247 33 05 Feb 2009 13 Feb 2009
10 Дроздков А.Н. (anddros) 147 146 21 356 260 6.074 6.723 31 11 Feb 2009 13 Feb 2009
11 Шиндин А.В. (AlShin) 147 150 21 355 79 20.458 7.203 30 05 Jan 2009 28 Jan 2009
12 Мурашкин И.В. (lepton) 142 150 21 342 995 47.797 37.312 30 12 Dec 2008 28 Jan 2009
13 >Умрихина Е.В. (Umrikhina) 146 146 21 353 295 13.521 15.879 28 13 Feb 2009 13 Feb 2009
14 Держальцев В.А. (MadVet) 137 146 21 333 1257 60.783 28.482 28 24 Sep 2008 30 Dec 2008
15 Любченко В.А. (IAS56) 136 146 21 332 615 403.343 373.617 28 11 May 2008 01 Dec 2008
16 Голубин Р.С. (Roman S. Golubin) 141 145 21 338 1260 93.162 58.822 25 29 Jan 2009 08 Feb 2009
17 Nikolaenko A.V. (Shadow77) 142 147 21 339 436 77.451 14.010 23 22 Oct 2008 11 Dec 2008
18 Солдатенков Ю.С. (SolYUtor) 138 146 21 331 819 22.615 6.102 20 14 Aug 2008 23 Oct 2008
19 Белогурова К. (Katy_Ekb) 133 143 21 321 552 10.666 4.673 18 27 Nov 2008 18 Jan 2009
20 Егоров А.Б. (ABEgorov) 137 144 21 329 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 >Ряшенцев Е.В. (Bagyr) 50 50 94 9 103 1580 13 Feb 2009
2 Mitin A. (Andrey321) 41 41 81 19 100 1666 12 Feb 2009
3 >Павленко Д.К. (Fantast) 25 52 46 34 80 980 13 Feb 2009
4 >___ _._. (_Nic) 33 48 72 0 72 1972 13 Feb 2009
5 >Голиков С.С. (Sergey) 37 37 71 0 71 2955 13 Feb 2009
6 >yuferov (yuf) 31 31 58 4 62 3238 13 Feb 2009
7 >Felonyuk I. (Innaf) 26 37 60 0 60 2891 13 Feb 2009
8 Кобылинский К.В. (k777) 32 32 60 0 60 3821 12 Feb 2009
9 >De Lima L.N. (R99) 19 43 43 0 43 2343 13 Feb 2009
10 >Rakovich A. (Lohmatyi) 17 106 38 0 38 208 13 Feb 2009
11 Таскин А.С. (Taskin) 21 21 36 0 36 6459 08 Feb 2009
12 >Andrey (mssqler) 17 44 33 0 33 2207 13 Feb 2009
13 Zlomanov (mastaflow) 14 25 32 0 32 5538 13 Feb 2009
14 >Какунина Т.О. (Moulin_Rouge) 11 28 27 3 30 4302 13 Feb 2009
15 >Cwiek G.Z. (gregor) 19 19 30 0 30 7470 13 Feb 2009
16 >Иванов П.Е. (Bonys) 18 44 23 6 29 2058 13 Feb 2009
17 >Kurylenko I.B. (Elts) 18 18 27 0 27 8125 13 Feb 2009
18 >Ребров (Dmitry78) 12 53 20 6 26 1000 13 Feb 2009
19 Krylova (Dictaphone) 18 18 26 0 26 7630 13 Feb 2009
20 >Гайдаенко Р.А. (Buzila) 9 20 24 0 24 6494 13 Feb 2009
21 Samoletova (SirenaS) 15 15 21 3 24 8711 10 Feb 2009
22 >Z E. (Elz) 11 97 23 0 23 254 13 Feb 2009
23 >Ротанин В.А. (userwar) 11 40 23 0 23 2500 13 Feb 2009
24 >Ичалов В. (a66at) 9 124 22 0 22 104 13 Feb 2009
25 Abraszek S. (Abraszek) 0 40 0 22 22 1622 13 Feb 2009
26 Макас (tensa_zangetsy) 10 22 19 3 22 6125 12 Feb 2009
27 Каратаев Е.А. (bliss910) 0 12 0 21 21 6758 13 Feb 2009
28 suvorov (ska) 10 38 20 0 20 2871 11 Feb 2009
29 >Татарова А.Е. (zyama) 14 14 20 0 20 9506 13 Feb 2009

Изучаем SQL

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

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

XML, основанный на схеме

В примерах выше я использовал нетипизированные документы XML, но Вы можете определить схему XML с помощью CREATE XML SCHEMA COLLECTION и вместо того, чтобы объявлять ваш параметр просто как xml, Вы можете указать xml (mycollection). SQL Server тогда будет проверять, насколько этот документ соответствует схеме. Я не вижу тут особого смысла с точки зрения альтернативы списку с разделителями-запятыми. Это может оказаться полезным для процедуры, которая выполняет вставку строки из более сложного документа.

Ориентированный на элементы XML

То, что Вы видели выше, называется ориентированным на атрибуты документом XML. Вы также можете использовать ориентированный на элементы XML, когда документ XML для ID продукции выглядит так:

<Root><Num>9</Num><Num>12</Num><Num>27</Num><Num>37</Num></Root>

В качестве первого параметра метода value Вы просто задаете единственный период, чтобы обозначить текущий элемент. Однако если у Вас нет особых причин использовать ориентированный на элементы XML, предпочтите ориентированный на атрибуты документ. В моих тестах "элементный" XML демонстрировал на 40-50 % большее время выполнения, чем "атрибутный" XML.

Кроме того, есть серьезная проблема, связанная с "элементным" XML в SQL 2005 SP2. Если Вы распакуете "элементный" документ XML в таблицу без кластерного индекса, то оптимизатор выберет такой план запроса, который является совершенным бедствием, когда документ генерирует много строк. Подробности можно посмотреть в сообщении о баге, о котором я заявил на сайте Майкрософт Connect site.

OPENXML

Уже в SQL 2000 Вы могли использовать XML благодаря функции OPENXML. OPENXML все еще имеется в SQL 2005, но единственная причина использовать его для Вас - это та, что вы должны также поддерживать SQL 2000. OPENXML слишком громоздкий для использования, и его производительность не соизмерима с методом nodes. Фактически, в моих тестах она была на 30-50 % ниже, чем для итерационного метода. Если Вы хотите посмотреть пример OPENXML, обратитесь, пожалуйста, к версии этой статьи для SQL 2000 (arrays-in-sql-2000.html).

Использование таблицы чисел

Это самый быстрый способ распаковать разделенный запятыми список чисел в чистом T-SQL. Трюк состоит в использовании вспомогательной таблицы чисел: таблицы с одним столбцом и числами от 1 и далее. Вот как Вы можете создать таблицу с числами от 1 до 999 999:

CREATE TABLE Numbers (Number int NOT NULL PRIMARY KEY);
WITH digits (d) AS (
   SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION
   SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION
   SELECT 7 UNION SELECT 8 UNION SELECT 9 UNION
   SELECT 0)
INSERT Numbers (Number)
   SELECT Number
   FROM   (SELECT i.d + ii.d * 10 + iii.d * 100 + iv.d * 1000 +
                  v.d * 10000 + vi.d * 100000 AS Number
           FROM   digits i
           CROSS  JOIN digits ii
           CROSS  JOIN digits iii
           CROSS  JOIN digits iv
           CROSS  JOIN digits v
           CROSS  JOIN digits vi) AS Numbers
   WHERE  Number > 0

См. конец раздела "Элементы массива постоянной длины", где приводится альтернативный способ создания таблицы чисел.

Встроенная функция

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

Рассматриваемую ниже функцию - inline_split_me первоначально предоставил мне SQL Server MVP Anith Sen. Оригинальная версия, которую я получил от Anith, представлена в версии статьи для SQL 2000. Ниже дана версия, модифицированная Brian W Perrin:

CREATE FUNCTION inline_split_me(@param nvarchar(MAX))
RETURNS TABLE AS
RETURN(SELECT ltrim(rtrim(convert(nvarchar(4000),
                  substring(@param, Number,
                            charindex(N',' COLLATE Slovenian_BIN2,
                                      @param + N',', Number) -
                            Number)
              ))) AS Value
       FROM   Numbers
       WHERE  Number <= convert(int, len(@param))
         AND  substring(N',' + @param, Number, 1) =
                        N',' COLLATE Slovenian_BIN2)
Go

В то время как итерационное решение было несколько длинноватым, но прямым, этот подход компактен, но не все читатели могут ухватить суть этого SQL сразу. (Я сам испытывал затруднения). Но давайте попытаемся понять, что этот зверь делает, и начнем с предложения WHERE. Первое условие:

Number <= convert(int, len(@param))

является простым. Переведенное в традиционное программирование, оно представляет собой цикл, который говорит "для всех символов в строке". Что касается convert, то я еще вернусь к этому. Второе условие:

substring(N',' + @param, Number, 1) = N','

отфильтровывает все позиции, где находится разделитель. Или, более точно, где начинается элемент списка. Первый элемент не имеет предшествующего разделителя, но мы обращаемся к нему с предшествующей @param запятой. Поскольку это сдвигает все символы на одну позицию, эта позиция и есть та позиция, откуда начинается элемент; символ после разделителя.

Ключевой момент - в списке SELECT:

substring(@param, Number,
          charindex(N',', @param + N',', Number) - Number)

Эта конструкция извлекает один элемент. Как я сказал выше, Number - это позиция, где начинается элемент. Затем мы находим конец элемента поиском следующего разделителя, определяя Number стартовой позицией для поиска, которая является третьим параметром в charindex. Для обработки конца строки мы дописываем запятую к @param. charindex возвращает позицию, а третий параметр в substring есть требуемая длина подстроки. Чтобы вычислить ее, мы просто вычитаем текущую позицию из позиции следующего разделителя.

SELECT также содержит такую конструкцию:

ltrim(rtrim(convert(nvarchar(4000)

Ее назначение - убрать начальные и конечные пробелы. И мы преобразовываем результат к nvarchar (4000), так как тип возвращаемого значения из substring совпадает с типом на входе, т.е. nvarchar (MAX). А как я отметил ранее, соединение nvarchar (MAX) с обычным столбцом nvarchar отрицательно сказывается на производительности.

Наконец, чтобы ускорить запрос, я принудительно использую бинарную коллацию в двух местах.

Вот пример того, как использовать эту конкретную функцию:

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

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

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

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

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

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

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

Контакты

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

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

В избранное