Как вывести одну строку sql

Функции FIRST_VALUE и LAST_VALUE

Для каждой компании выводить один рейс, выбираемый случайным образом

Использование коррелирующего подзапроса

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

id_comptrip_no
11188
21146
31124
41101
57771

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

Использование функции FIRST_VALUE

Эта оконная функция возвращает первое из упорядоченного набора значений. Теперь мы можем сделать все без подзапросов, выделив в окне набор рейсов для компании из текущей строки запроса с помощью предложения PARTITION BY и упорядочив его, как и в предыдущем примере, случайным образом в предложении ORDER BY:

id_comptrip_no
11195
21145
31124
41100
58882

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

Засада с LAST_VALUE

Казалось бы, какая разница брать первое или последнее значение из случайным образом упорядоченного набора? Но давайте посмотрим, что мы получим, если в предыдущем запросе заменить FIRST_VALUE на LAST_VALUE:

Я приведу результаты только для id_comp = 1. Вы можете сами выполнить запрос, чтобы убедиться, что будут выводиться абсолютно все рейсы из таблицы Trip.

id_comptrip_no
11181
11182
11187
11188
11195
11196

Что мы делаем в подобных случаях? Конечно, обращаемся к документации, а там мы читаем. Нет, постойте, сначала полный синтаксис:

Здесь
IGNORE NULLS или RESPECT NULLS определяют, будут ли учитываться NULL-значения;
предложение_rows_range задает параметры окна.

Диапазоном по умолчанию является RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW.

Т.е. окном является диапазон от текущей строки и неограниченно выше. Поскольку мы выбираем последнюю строку диапазона, то всегда будет выводиться текущая строка, как бы не сортировались строки. Т.е. сколько бы строк выше не оказалось при случайной сортировке.

Потому и DISTINCT не помогает, т.к. все выводимые строки оказываются уникальными.

Значит нам просто нужно явно (и правильно!) задать параметры окна, а именно, от текущей строки и неограниченно ниже, поскольку мы выбираем последнее значение:

Источник

Как в SQL получить первые (или последние) строки запроса? TOP или OFFSET?

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

Как вывести одну строку sql. Смотреть фото Как вывести одну строку sql. Смотреть картинку Как вывести одну строку sql. Картинка про Как вывести одну строку sql. Фото Как вывести одну строку sql

В языке T-SQL существует две стандартные возможности, которые позволяют нам применить фильтр к результирующему набору данных, иными словами, оставить в результате только определённое количество строк. Это могут быть первые строки, с учётом сортировки, что достаточно часто требуется при работе с базами данных на SQL, или последние строки, а также существует возможность вывести любой набор строк, например, пропустить первые строки и вывести определённое количество следующих строк.

Как я уже отметил, существует два способа фильтрации результирующего набора данных, первый – это использование фильтра TOP, и второй – это использование конструкции OFFSET-FETCH, которую мы подробно рассмотрели в отдельном материале — «OFFSET-FETCH в T-SQL – описание и примеры использования».

Получаем первые строки результата SQL запроса

Сейчас давайте я покажу, как можно вывести первые строки результирующего набора данных, сначала мы рассмотрим пример с использованием TOP, а затем сделаем то же самое только с помощью OFFSET-FETCH.

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

Исходные данные для примеров

В качестве сервера у меня выступает Microsoft SQL Server 2016 Express. А теперь давайте представим, что у нас есть таблица TestTable и в ней содержатся следующие данные (перечень товаров с указанием цены).

Как вывести одну строку sql. Смотреть фото Как вывести одну строку sql. Смотреть картинку Как вывести одну строку sql. Картинка про Как вывести одну строку sql. Фото Как вывести одну строку sql

Получаем первые строки запроса с помощью TOP

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

Синтаксис

TOP (Число строк) [PERCENT]

У инструкции TOP несколько параметров:

Фильтр TOP обычно применяется с сортировкой данных (ORDER BY), однако это необязательно, можно применять данный фильтр и без сортировки данных, только в этом случае строки будут возвращаться в произвольном порядке (так, как они хранятся).

Пример SQL запроса с TOP – выводим первые 5 строк

Допустим, нам нужно получить 5 самых дорогих товаров, для этого пишем следующий запрос.

Как вывести одну строку sql. Смотреть фото Как вывести одну строку sql. Смотреть картинку Как вывести одну строку sql. Картинка про Как вывести одну строку sql. Фото Как вывести одну строку sql

В данном случае мы указали сортировку по уменьшению цены (ORDER BY Price DESC), а также применили фильтр TOP (5), для ограничения вывода строк результирующего набора.

Пример SQL запроса с TOP и параметром WITH TIES

Сейчас давайте запустим два запроса, в обоих случаях мы будем запрашивать 4 самых дорогих товара, т.е. применим фильтр TOP (4), однако во втором запросе дополнительно мы укажем параметр WITH TIES и посмотрим на разницу итогового результата.

Как вывести одну строку sql. Смотреть фото Как вывести одну строку sql. Смотреть картинку Как вывести одну строку sql. Картинка про Как вывести одну строку sql. Фото Как вывести одну строку sql

В итоге мы очень хорошо видим разницу, в первом случае вывелось 4 строки, а во втором 5, так как товар в 5 строке имеет точно такую же цену, как и товар в 4 строке.

Пример SQL запроса с TOP и параметром PERCENT

В этом примере давайте просто выведем 50 процентов итогового набора записей, т.е. половину. Для этого мы используем параметр PERCENT.

Как вывести одну строку sql. Смотреть фото Как вывести одну строку sql. Смотреть картинку Как вывести одну строку sql. Картинка про Как вывести одну строку sql. Фото Как вывести одну строку sql

Так как у нас в таблице TestTable всего 8 записей, нам вывелось 4 строки, т.е. как раз 50 процентов.

Получаем первые строки запроса с помощью OFFSET-FETCH

Вторым способом получения первых строк является использование конструкции OFFSET-FETCH, однако она появилась только в 2012 версии SQL сервер, до этого, соответственно, этот способ использовать не получится.

У конструкции OFFSET-FETCH отсутствуют такие параметры, как PERCENT и WITH TIES, которые есть у фильтра TOP, однако у OFFSET-FETCH есть одно очень важное преимущество – это возможность пропускать определенное количество первых строк.

Примечание! OFFSET-FETCH — это часть конструкции ORDER BY, поэтому без сортировки использовать OFFSET-FETCH не удастся. Также не получится одновременно использовать OFFSET-FETCH и TOP в одном запросе SELECT.

Пример SQL запроса с OFFSET-FETCH — выводим первые 5 строк

Чтобы вывести первые строки с помощью конструкции OFFSET-FETCH, нам нужно в секции OFFSET указать 0, т.е. начинать вывод сразу с первой строки (если указать другое число, то именно такое количество строк будет пропущено). В секции FETCH мы соответственно указываем 5.

Как вывести одну строку sql. Смотреть фото Как вывести одну строку sql. Смотреть картинку Как вывести одну строку sql. Картинка про Как вывести одну строку sql. Фото Как вывести одну строку sql

Результат, мы видим, точно такой же, как и в случае с TOP.

Как вывести последние строки SQL запроса?

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

Получаем последние строки SQL запроса с помощью TOP

В случае с TOP нам дополнительно потребуется использовать конструкцию WITH (CTE – обобщенное табличное выражение), для того чтобы выполнить сортировку по идентификатору для применения фильтра TOP, т.е. отобрать самые последние записи. А после этого мы уже можем отсортировать строки так, как нам нужно.

Как вывести одну строку sql. Смотреть фото Как вывести одну строку sql. Смотреть картинку Как вывести одну строку sql. Картинка про Как вывести одну строку sql. Фото Как вывести одну строку sql

Как видите, нам вывелись 5 последних строк.

Получаем последние строки SQL запроса с помощью OFFSET-FETCH

Для получения последних строк с помощью OFFSET-FETCH нам потребуется предварительно узнать общее количество строк, для того чтобы определить, сколько строк нужно пропустить. Это можно сделать как с помощью вложенного запроса, так и с помощью предварительного сохранения нужного нам значения в переменной. Я покажу способ с использованием переменной.

Как вывести одну строку sql. Смотреть фото Как вывести одну строку sql. Смотреть картинку Как вывести одну строку sql. Картинка про Как вывести одну строку sql. Фото Как вывести одну строку sql

Итоговый результат такой же, как и в запросе с TOP.

Теперь Вы знаете, как с помощью TOP и OFFSET получать первые и последние строки результирующего набора данных, который возвращает SQL запрос.

В данной статье мы затронули одну очень маленькую возможность языка T-SQL, но их, как Вы понимаете, гораздо больше, поэтому, если Вы начинающий программист и хотите изучить язык T-SQL, то рекомендую посмотреть мои видеокурсы по T-SQL, с помощью которых Вы «с нуля» научитесь работать с SQL и программировать на T-SQL.

У меня на этом все, удачи в освоении языка T-SQL!

Источник

Функции работы со строками в MS SQL SERVER 2005

Вот полный перечень функций работы со строками, взятый из BOL:

ASCIINCHARSOUNDEX
CHARPATINDEXSPACE
CHARINDEXREPLACESTR
DIFFERENCEQUOTENAMESTUFF
LEFTREPLICATESUBSTRING
LENREVERSEUNICODE
LOWERRIGHTUPPER
LTRIMRTRIM

Функция ASCII возвращает ASCII-код крайнего левого символа строкового выражения, являющегося аргументом функции.

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

SELECT COUNT(DISTINCT ASCII(name)) FROM Ships

SELECT DISTINCT CHAR(ASCII(name)) FROM Ships ORDER BY 1

и вырезает заданное вторым аргументом число символов слева из строки, являющейся первым аргументом. Итак,

SELECT DISTINCT LEFT(name, 1) FROM Ships ORDER BY 1

А вот как, например, можно получить таблицу кодов всех алфавитных символов:

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

SELECT ASCII(‘ё’) UNION ALL SELECT ASCII(‘Ё’)

Я полагаю, что не будет сложным добавить эту букву в таблицу, если потребуется.

CHARINDEX (искомое_выражение, строковое_выражение[, стартовая_позиция])

SELECT name FROM Ships WHERE CHARINDEX(‘sh’, name) > 0

будет выводить те корабли, в которых имеется сочетание символов «sh». Здесь используется тот факт, что если искомая строка не будет обнаружена, то функция CHARINDEX возвращает 0. Результат выполнения запроса будет содержать следующие корабли:

name
Kirishima
Musashi
Washington

Следует отметить, что если искомая подстрока либо строковое выражение есть NULL, то результатом функции тоже будет NULL.

Следующий пример определяет позиции первого и второго вхождения символа «a» в имени корабля «California»

SELECT CHARINDEX(‘a’,name) first_a,
CHARINDEX(‘a’, name, CHARINDEX(‘a’, name)+1) second_a
FROM Ships WHERE name=’California’

Функция PATINDEX имеет синтаксис:

SELECT name FROM Ships WHERE PATINDEX(‘%sh%’, name) > 0

А вот, например, как можно найти имена кораблей, которые содержат последовательность из трех символов, первый и последний из которых есть «e»:

SELECT name FROM Ships WHERE PATINDEX(‘%e_e%’, name) >0

Результат выполнения этого запроса выглядит следующим образом:

name
Revenge
Royal Sovereign

Парная к LEFT функция RIGHT возвращает заданное число символов справа из строкового выражения:

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

SELECT name FROM Ships WHERE LEFT(name, 1) = RIGHT(name, 1)

Соединение двух строковых значений в одно называется конкатенацией, и в SQL Server для этой операции используется знак «+» (в стандарте «||»). Итак,

SELECT * FROM (
SELECT class +’ ‘+ name AS cn FROM Ships
) x
WHERE LEFT(cn, 1)=RIGHT(cn, 1)

Здесь мы разделяем пробелом имя класса и имя корабля. Кроме того, чтобы не повторять всю конструкцию в качестве аргумента функции, используем подзапрос. Результат будет иметь вид:

cn
Iowa Missouri
North Carolina Washington

А если строковое выражение будет содержать лишь одну букву? Запрос выведет ее. В этом легко убедиться, написав

SELECT * FROM (
SELECT class +’ ‘+ name AS cn FROM Ships
UNION ALL
SELECT ‘a’ as nc
) x
WHERE LEFT(cn, 1)=RIGHT(cn, 1)

Чтобы исключить этот случай, можно воспользоваться еще одной полезной функцией LEN ( ), которая возвращает число символов в строке. Ограничимся случаем, когда число символов больше единицы:

SELECT * FROM (
SELECT class +’ ‘+ name AS cn FROM Ships
UNION ALL
SELECT ‘a’ as nc
) x
WHERE LEFT(cn, 1)=RIGHT(cn, 1) AND LEN(cn)>1

Замечание. Реализация этой функции в MS SQL Server имеет одну особенность, а именно, при подсчете длины не учитываются концевые пробелы.
Действительно, выполним следующий код:

DECLARE @chr AS CHAR(12), @vchr AS VARCHAR(12)

SELECT @chr = ‘abcde’ + REPLICATE(‘ ‘, 5), @vchr = ‘abcde’+REPLICATE(‘ ‘, 5)

SELECT LEN(@chr), LEN(@vchr)
SELECT DATALENGTH(@chr), DATALENGTH(@vchr)

55
1210

На сайте имеются задачи, в которых требуется упорядочить (найти максимум и т.д.) в числовом порядке значения, представленные в текстовом формате. Например, номер места в самолете («2d») или скорость CD («24x»). Проблема заключается в том, что текст сортируется так (по возрастанию)

SELECT ‘1a’ AS place
UNION ALL SELECT ‘2a’
UNION ALL SELECT ’11a’
ORDER BY 1

Если же требуется упорядочить места в порядке возрастания рядов, то порядок должен быть такой

Чтобы добиться такого порядка, нужно выполнить сортировку по числовым значениям, присутствующим в тексте. Можно предложить такой алгоритм:
1. Извлечь число из строки.
2. Привести его к числовому формату.
3. Выполнить сортировку по приведенному значению.

Т.к. нам известно, что буква только одна, то для извлечения числа из строки можно воспользоваться следующей конструкцией, которая не зависит от числа цифр в номере места:

LEFT(place, LEN(place)-1)

Если только этим и ограничиться, то получим

place
1a
11a
2a

Приведение к числовому формату может быть следующим:

CAST (LEFT(place, LEN(place)-1) AS INT)

Осталось выполнить сортировку

SELECT * FROM (
SELECT ‘1a’ AS place
UNION ALL SELECT ‘2a’
UNION ALL SELECT ’11a’
) x
ORDER BY CAST(LEFT(place, LEN(place)-1) AS INT)

Что и требовалось доказать.

Ранее мы для извлечения числа из текстовой строки пользовались функцией LEFT, т.к. нам было известно априори, какое число символов нужно убрать справа (один). А если же нужно извлечь строку из подстроки не по известной позиции символа, а по самому символу? Например: извлечь все символы до первой буквы «х» (значение скорости CD).

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

Функция SUBSTRING

Эта функция позволяет извлечь из выражения его часть заданной длины, начиная от заданной начальной позиции. Выражение может быть символьной или бинарной строкой, а также иметь тип text или image. Например, если нам потребуется получить 3 символа в названии корабля, начиная со 2-го символа, то сделать без помощи функции SUBSTRING будет не так просто. А так мы пишем:

SELECT name, SUBSTRING(name, 2, 3) FROM Ships

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

SELECT name, SUBSTRING(name, 2, LEN(name)) FROM Ships

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

Функция REVERSE

Эта функция переворачивает строку, как бы читая ее справа налево. Т.е. результатом запроса

SELECT REVERSE(‘abcdef’)

будет ‘fedcba’. Если бы в языке отсутствовала функция RIGHT, то запрос

SELECT RIGHT(‘abcdef’,3)

можно было бы равносильно заменить запросом

SELECT REVERSE(LEFT(REVERSE(‘abcdef’),3))

Я вижу пользу этой функции в следующем. Пусть нам требуется определить позицию не первого, а последнего вхождения некоторого символа (или последовательности символов) в строке. Вспомним пример, в котором мы определяли позицию первого символа «а» в названии корабля «California»:

SELECT CHARINDEX(‘a’, name) first_a
FROM Ships WHERE name=’California’

Определим теперь позицию последнего вхождения в это название символа «а». Функция

CHARINDEX(‘a’, REVERSE(name))

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

Функция REPLACE

Заменяет в строке1 все вхождения строки2 на строку3. Эта функция, безусловно, полезна в операторах обновления (UPDATE), если нужно изменить (исправить) содержимое столбца. Пусть, например, нужно заменить все пробелы дефисом в названиях кораблей. Тогда можно написать

UPDATE Ships
SET name = REPLACE(name, ‘ ‘, ‘-‘)

(Этот пример можно выполнить на странице с упражнениями DML, где разрешаются запросы на изменение данных)

Однако эта функция может найти применение и в более нетривиальных случаях. Давайте определим, сколько раз в названии корабля используется буква «a». Идея проста: заменим каждую искомую букву двумя любыми символами, после чего посчитаем разность длин полученной и искомой строки. Итак,

А если нам нужно определить число вхождений произвольной последовательности символов, скажем, передаваемой в качестве параметра в хранимую процедуру? Использованный выше алгоритм в этом случае следует дополнить делением на число символов в искомой последовательности:

Если же нужно заменить в строке не определенную последовательность символов, а заданное число символов, начиная с некоторой позиции, то проще использовать функцию STUFF:

Эта функция заменяет подстроку длиной L, которая начинается со стартовой позиции в строке1, на строку2.

Пример. Изменить имя корабля: оставив в его имени 5 первых символов, дописать «_» (нижнее подчеркивание) и год спуска на воду. Если в имени менее 5 символов, дополнить его пробелами.

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

SELECT name, STUFF(name, 6, LEN(name), ‘_’+launched) FROM Ships

При этом преобразовании выполняется округление, а длина задает длину результирующей строки. Например,

STR(3.3456, 5, 1)3.3
STR(3.3456, 5, 2)3.35
STR(3.3456, 5, 3)3.346
STR(3.3456, 5, 4)3.346

Обратите внимание, что если полученное строковое представление числа меньше заданной длины, то добавляются лидирующие пробелы. Если же результат больше заданной длины, то усекается дробная часть (с округлением); в случае же целого числа получаем соответствующее число звездочек «*»:

Кстати, по умолчанию используется длина в 10 символов. Имея в виду, что год представлен четырьмя цифрами, напишем

SELECT name, STUFF(name, 6, LEN(name), ‘_’+STR(launched, 4)) FROM Ships

Уже почти все правильно. Осталось учесть случай, когда число символов в имени менее 6, т.к. в этом случае функция STUFF дает NULL. Ну что ж вытерпим до конца мучения, связанные с использованием этой функции в данном примере, попутно применив еще одну строковую функцию. Добавим конечные пробелы, чтобы длина имени была заведомо больше 6. Для этого имеется специальная функция SPACE

SELECT name, STUFF(name + SPACE(6), 6, LEN(name), ‘_’+STR(launched,4)) FROM Ships

Функции LTRIM и RTRIM

отсекают соответственно лидирующие и конечные пробелы строкового выражения, которое неявно приводится к типу VARCHAR.

Пусть требуется построить такую строку: имя пассажира_идентификатор пассажира для каждой записи из таблицы Passenger. Если мы напишем

SELECT name + ‘_’ + CAST(id_psg AS VARCHAR) FROM Passenger,

то в результате получим что-то типа:

Это связано с тем, что столбец name имеет тип CHAR(30). Для этого типа короткая строка дополняется пробелами до заданного размера (у нас 30 символов). Здесь нам как раз и поможет функция RTRIM:

SELECT RTRIM(name) + ‘_’ + CAST(id_psg AS VARCHAR) FROM Passenger

Функции LOWER и UPPER

преобразуют все символы аргумента соответственно к нижнему и верхнему регистру. Эти функции оказываются полезными при сравнении регистрозависимых строк.

Пара интересных функций SOUNDEX и DIFFERENCE:

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

В заключение приведем функции и несколько примеров использования юникода.

Функция UNICODE

возвращает юникод первого символа строкового выражения.

Функция NCHAR

возвращает символ по его юникоду. Несколько примеров.

SELECT ASCII(‘а’), UNICODE(‘а’)

возвращает код ASCII и юникод русской буквы «а»: 224 и 1072.

SELECT CHAR(ASCII(‘а’)), CHAR(UNICODE(‘а’))

Пытаемся восстановить символ по его коду. Получаем «а» и NULL. NULL-значение возвращается потому, что кода 1072 нет в обычной кодовой таблице.

SELECT CHAR(ASCII(‘а’)), NCHAR(UNICODE(‘а’))

Теперь все нормально, в обоих случаях «а». Наконец,

SELECT NCHAR(ASCII(‘а’))

даст «a», т.к. юникод 224 соответствует именно этой букве.

Приведенные здесь примеры можно выполнить непосредственно на сайте, установив флажок «Без проверки» на странице с упражнениями на SELECT.

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *