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

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


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

Выпуск 238 от 18 апреля 2009 г.

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

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

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

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

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


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

§ Ростовчан приглашаем посетить семинар, посвященный SQL Server 2008.
Доклад сделает Алексей Шуленин (Майкрософт):

Там, за облаками. Microsoft SQL Server и концепция приложений в "облаке"

Семинар состоится 29 апреля (начало в 16:00) по адресу:
ул. Мильчакова 10 (здание НКТБ Пьезоприбор), Факультет высоких технологий ЮФУ, а. 514 (5 этаж)

 

§ Произошла замена задач 4-6, 50. Старые задачи перешли на обучающий этап.
На место 50 задачи поставлена прежняя 70; Второй этап теперь начинается с 50-й задачи.
Под номером 70 теперь находится новая задача (сложность 1).
Выставлены новые задачи на третий этап:
155 (автор vlksm, 2 балла),
156 (автор anddros, 2 балла).

§ Добавил подсказки к задачам 5, 55, 118.

§ На форуме рейтинговых задач открыт новый топик - 800. Здесь вы можете задавать и отвечать на вопросы по SQL, непосредственно не связанные с решением задач на сайте.

§ Изменения среди лидеров (решенные за неделю задачи третьего этапа):
Смена лидера!
1. vlksm (155)
4. Ozzy (152)
5. Umrikhina (152)
8. anddros (156)
24. AKudrakov (151)

§ К третьему этапу подошел (до замены задач):
97. Avtolic (задач 138, время 16.547)

§ Продвинулись в рейтинге:
50. _Bkmz_ (136, 5.933)
51. B o r i s (133, 195.708)
52. Oxana (132, 73.386)
70. Nariman Kurbanoff (127, 103.180)

§ Новые лица в ТОР 100 и вернувшиеся туда:
97. Avtolic (134, 16.547)

§ Продвижение ближайших претендентов на попадание в ТОР 100:
123. maar (117, 88.677)
131. _irina_ (116, 27.189)
152. Wiedzmen (115, 8.296)
156. GrImago (114, 15.990)

§ На этой неделе сертифицированы:
EvGeniy Lell (A09039945) [BK] - г.Днепропетровск, Украина
Лабутин П.А. (A09002429) [BK] - г.Хабаровск, Россия

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

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

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

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

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

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

No Person Number of
Sel_ex
Last_Sel Number of
DML_ex
Scores Days Days_2 Days_3 S_3 LastSolved LastVisit
1 >Карасёва Н.В. (vlksm)1 155 70 21 376 1077 90.188 61.061 55 17 Apr 2009 17 Apr 2009
2 >Креславский О.М. (Arcan)1 154 70 21 374 808 65.291 46.391 53 17 Apr 2009 17 Apr 2009
3 >Сальников С.А. ($erges)1 152 6 21 369 416 3.854 4.191 49 17 Apr 2009 17 Apr 2009
4 Зотов П.Г. (Ozzy)4 146 153 21 357 400 138.633 155.555 49 14 Apr 2009 17 Apr 2009
5 >Умрихина Е.В. (Umrikhina)5 151 6 21 366 358 24.059 26.418 46 17 Apr 2009 17 Apr 2009
6 Сенкевич С.В. (GreyC)1 148 152 21 363 358 57.860 27.102 46 26 Jan 2009 14 Apr 2009
7 Селезнёв А.С. (Артём С.)1 146 152 21 357 444 47.248 37.524 46 25 Jan 2009 03 Mar 2009
8 >Дроздков А.Н. (anddros)7 151 70 21 365 325 6.474 7.110 44 17 Apr 2009 17 Apr 2009
9 Никотин В.М. (@Nikotin)1 146 150 21 357 108 8.371 3.751 40 13 Dec 2008 17 Apr 2009
10 Печатнов В.В. (pvv)1 142 149 21 344 357 30.849 17.490 36 10 Oct 2008 17 Apr 2009
11 Мурашкин И.В. (lepton)1 140 152 21 340 1066 68.477 57.992 36 21 Feb 2009 10 Apr 2009
12 Муллаханов Р.Х. (rem)9 145 152 21 352 483 14.427 20.056 35 05 Jan 2009 10 Apr 2009
13 Шиндин А.В. (AlShin)10 143 150 21 347 79 20.458 7.203 30 05 Jan 2009 28 Jan 2009
14 Держальцев В.А. (MadVet)7 133 146 21 325 1257 60.783 28.482 28 24 Sep 2008 30 Dec 2008
15 Любченко В.А. (IAS56)6 132 146 21 324 615 403.343 373.617 28 11 May 2008 01 Dec 2008
16 Голубин Р.С. (Roman S. Golubin)3 137 145 21 330 1260 93.162 58.822 25 29 Jan 2009 08 Feb 2009
17 Nikolaenko A.V. (Shadow77)12 138 147 21 331 436 77.451 14.010 23 22 Oct 2008 11 Dec 2008
18 Солдатенков Ю.С. (SolYUtor)2 134 146 21 323 819 22.615 6.102 20 14 Aug 2008 01 Apr 2009
19 Белогурова К. (Katy_Ekb)19 129 143 21 313 552 10.666 4.673 18 27 Nov 2008 18 Jan 2009
20 Егоров А.Б. (ABEgorov)20 133 144 21 321 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 Кононов А.Е. (AlexSoft) 33 47 62 28 90 1089 16 Apr 2009
2 >Ершов А.Н. (basik) 38 38 78 0 78 2340 17 Apr 2009
3 >Павлов В.Г. (Павлов) 31 39 67 0 67 2439 17 Apr 2009
4 >Ушаков С.В. (Cliper29) 19 27 44 17 61 2822 17 Apr 2009
5 SL! S.S. (SL1) 27 27 53 0 53 4284 12 Apr 2009
6 Anvd (Anvd) 25 25 52 0 52 4363 11 Apr 2009
7 Чернопятнов А.С. (GuestA) 21 30 47 3 50 3707 16 Apr 2009
8 Фамилия (SimaYang) 19 29 45 2 47 3109 15 Apr 2009
9 >Ларина Ю. (Gerda) 24 24 46 0 46 5063 17 Apr 2009
10 Гарифзянов Т. (garifzyanov) 7 48 11 34 45 1022 15 Apr 2009
11 >temp (euro) 22 22 43 0 43 5403 17 Apr 2009
12 >Ssp (Baumanec) 19 47 34 8 42 1398 17 Apr 2009
13 >St D. (Dmitriy_S) 14 59 20 17 37 772 17 Apr 2009
14 >Глебов В. (Zidane) 20 20 37 0 37 6207 17 Apr 2009
15 Ветошкин И. (karam6anita) 18 18 33 3 36 6349 17 Apr 2009
16 >Осадчий В.В. (Mathematician) 19 89 35 0 35 283 17 Apr 2009
17 Приходько А. (can) 17 20 35 0 35 6084 17 Apr 2009
18 >marat (lemon) 19 97 33 0 33 254 17 Apr 2009
19 Рогачёв А.А. (aint) 2 50 2 31 33 990 13 Apr 2009
20 Бейльханов Д. (Damir_31) 10 47 14 19 33 1179 16 Apr 2009
21 Лабутин П.А. (Лабутин П.А.) 17 63 28 4 32 640 17 Apr 2009
22 mr T.K. (thangdogg) 15 18 30 0 30 5594 13 Apr 2009
23 Бурнаковский А.П. (Aristarkh) 17 17 30 0 30 7053 16 Apr 2009

Изучаем SQL

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

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

Однако производительность этой процедуры, как и подобной ей, использующей INSERT VALUES, оставляет желать лучшего. Приличной производительности удается достичь, если мы используем трюк с INSERT-EXEC и большим числом небольших операторов SELECT, предложенный Джимом Эбберсом (Jim Ebbers). Ниже представлена эта процедура, определенно более сложная, чем представленная выше.

CREATE PROCEDURE unpack_with_manyselect
                 @list      nvarchar(MAX),
                 @tbl       varchar(30),
                 @delimiter nchar(1) = ',' AS
DECLARE @sql nvarchar(MAX),
        @q1     char(1),
        @q2     char(2)
SELECT @q1 = char(39), @q2 = char(39) + char(39)
SELECT @sql = 'INSERT ' + @tbl + ' EXEC(' + @q1 + 'SELECT ' +
               replace(replace(@list, @q1 COLLATE Slovenian_BIN2, @q2 + @q2),
                       @delimiter COLLATE Slovenian_BIN2,
                       ' SELECT ') + @q1 + ')'
--PRINT @sql
EXEC (@sql)

Здесь внутренний replace заменяет одиночную кавычку в @list не менее чем четырьмя одиночными кавычками. Это связано с тем, что сам INSERT EXEC вложен в EXEC(). (Вы могли догадаться, почему у меня там стоит закомментированный PRINT @sql !) В эту процедуру я также добавил предложение COLLATE. (Другая процедура настолько медленна, что COLLATE там не оказывает никакого влияния на производительность.)

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

CREATE PROCEDURE unpackstr_with_manyselect
                 @list      nvarchar(MAX),
                 @tbl       varchar(30),
                 @delimiter nchar(1) = ',' AS
DECLARE @sql    nvarchar(MAX),
        @q1     char(1),
        @q2     char(2)
SELECT @q1 = char(39), @q2 = char(39) + char(39)
SELECT @sql = 'INSERT ' + @tbl +
               ' EXEC(' + @q1 + 'SELECT ltrim(rtrim(' + @q2 +
               replace(replace(@list, @q1 COLLATE Slovenian_BIN2, @q2 + @q2),
                       @delimiter COLLATE Slovenian_BIN2,
                       @q2 + ')) SELECT ltrim(rtrim(' + @q2) +
               @q2 + '))' + @q1 + ')'
--PRINT @sql
EXEC (@sql)

Пример использования:

CREATE PROCEDURE get_company_names_manyselect @custids nvarchar(2000) AS
   CREATE TABLE #temp (custid nchar(5) NULL)

   EXEC unpackstr_with_manyselect @custids, '#temp'

   SELECT C.CompanyName, C.CustomerID
   FROM   Northwind..Customers C
   JOIN   #temp t ON C.CustomerID = t.custid
go
EXEC get_company_names_manyselect 'ALFKI, BONAP, CACTU, FRANK'

Действительно ли этот метод представляет собой хорошую альтернативу для обработки списков с разделителями-запятыми? Нет. Производительность для списков целых чисел сравнима с итерационным методом, но значительно медленнее для списков строк. Итерационный метод имеет преимущество в его легкой адаптации под различные форматы на входе и простом получении дополнительной информация типа позиции в списке. unpack_with_manyselect ничего этого не дает. Его сильная сторона - вставка большого числа значений.

Замечание. Все рассмотренные здесь процедуры включают INSERT. Но Вы можете выбросить INSERT из процедуры, и вместо него вызывать процедуру из INSERT EXEC. В этом случае Вы на выбор можете использования либо временные таблицы, либо табличные переменные.

Действительно медленные методы

В колонке Q&A журнала SQL journal один SQL Server MVP, обращаясь к другому MVP, предложил следующее решение:

CREATE PROCEDURE get_company_names_charindex @customers nvarchar(2000) AS
SELECT CustomerID, CompanyName
FROM   Northwind..Customers
WHERE  charindex(',' + CustomerID + ',', ',' + @customers + ',') > 0
go
EXEC get_company_names_charindex 'ALFKI,BONAP,CACTU,FRANK'

Вы можете узнать эту тему по нашему использованию таблицы чисел. Добавляя запятые по обеим сторонам входной строки, мы можем использовать charindex, чтобы найти, ",ALFKI," и т.д. (Заметим, что здесь мы не можем иметь вложенных пробелов.)

Автор отметил в своей колонке, что этот метод не будет обладать хорошей производительностью, поскольку включение столбца таблицы в выражение препятствует использованию любого индекса на этом столбце, приводя к сканированию таблицы. Но это далеко не все. Простое сканирование таблицы на моей тестовой таблице заняло 800 миллисекунд, когда таблица полностью находится в кэше. Этот метод потребовал 65 секунд для входного списка из 20 строк!

Вариации на эту тему иллюстрируются следующими предложениями WHERE:

WHERE  patindex('%,' + CustomerID + ',%',   ',' + @customers + ',') > 0
WHERE  ',' + @customers + ','   LIKE    '%,' + CustomerID + ',%'

Решение с LIKE так же медленно или даже медленнее, чем charindex. Я никогда не проверял patindex на 2005 SQL.

Здесь есть "переключатель скорости ": предложение COLLATE. Добавьте предложение COLLATE для приведения к бинарной коллации, и производительность улучшается в 7-10 раз. Но проблема состоит в том, что, если Вы передаете строку типа alfki,bonap,cactu,frank, то можете все еще ожидать прирост, которого Вы не получили бы с бинарной коллацией. Поэтому в моих тестах, я применял коллацию только тогда, когда на вход подавался список целых чисел, как в этом примере:

CREATE PROCEDURE get_product_names_realslow @ids varchar(200) AS
SELECT ProductName, ProductID
FROM   Northwind..Products
WHERE  charindex(',' + ltrim(str(ProductID)) + ',' COLLATE Slovenian_BIN2,
                 ',' + @ids + ',' COLLATE Slovenian_BIN2) > 0
go
EXEC get_product_names_realslow '9,12,27,37'

Если Вы используете коллацию SQL, Вы также получаете такой же огромный прирост производительности, если можете ограничиться типом varchar (и нечувствительностью к регистру).

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

Заключение

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

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

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

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

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

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

Контакты

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

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

В избранное