Вчера на собеседовании мне задали этот вопрос, и я понятия не имел об этом. Предположим, у меня есть слово "Манхэттен", я хочу отображать только буквы "M", "A", "N", "H", "T", в SQL. Как это сделать? Любая помощь приветствуется.
Как разделить и отобразить различные буквы из слова в SQL?
Ответ 1
Ну, вот мое решение (sqlfiddle) - оно предназначено для использования операций Relational SQL, которые могли быть что интервьюер собирался концептуально.
Большая часть проделанной работы - просто превратить строку в набор записей (pos, letter) в качестве соответствующих окончательных применений DQL является простым SELECT с применением группировки и упорядочения.
select letter
from (
-- All of this just to get a set of (pos, letter)
select ns.n as pos, substring(ss.s, ns.n, 1) as letter
from (select 'MANHATTAN' as s) as ss
cross join (
-- Or use another form to create a "numbers table"
select n from (values (1),(2),(3),(4),(5),(6),(7),(8),(9)) as X(n)
) as ns
) as pairs
group by letter -- guarantees distinctness
order by min(pos) -- ensure output is ordered MANHT
Вышеупомянутый запрос работает в SQL Server 2008, но "Таблица номеров" , возможно, придется изменить для других поставщиков. В противном случае нет ничего, что специфично для конкретного поставщика - нет CTE или перекрестного применения функции или кода процедурного языка.
Таким образом, вышесказанное должно показать концептуальный подход - SQL предназначен для использования с наборами и отношениями и множественностью записей; приведенный выше пример, в некотором смысле, является просто извращением такого.
Изучая промежуточное отношение,
select ns.n as pos, substring(ss.s, ns.n, 1) as letter
from (select 'MANHATTAN' as s) as ss
cross join (
select n from (values (1),(2),(3),(4),(5),(6),(7),(8),(9)) as X(n)
) as ns
использует cross join для создания декартова произведения строки (1 строка) с числами (9 строк); тогда функция substring
применяется со строкой и каждым числом для получения каждого символа в соответствии с его положением. Результирующий набор содержит записи -
POS LETTER
1 M
2 A
3 N
..
9 N
Затем внешний выбор группирует каждую запись в соответствии с буквой, а результирующие записи упорядочиваются по минимальной (первой) позиции вхождения буквы, которая устанавливает группировку. (Без порядка по буквам было бы отличным, но окончательный порядок не гарантировался бы.)
Ответ 2
Один из способов (при использовании SQL Server) находится с рекурсивная СТЕ (Коммон Таблица Выражение).
DECLARE @source nvarchar(100) = 'MANHATTAN'
;
WITH cte AS (
SELECT SUBSTRING(@source, 1, 1) AS c1, 1 as Pos
WHERE LEN(@source) > 0
UNION ALL
SELECT SUBSTRING(@source, Pos + 1, 1) AS c1, Pos + 1 as Pos
FROM cte
WHERE Pos < LEN(@source)
)
SELECT DISTINCT c1 from cte
SqlFiddle для этого здесь. Мне пришлось встроить @source
для SqlFiddle, но код выше отлично работает на Sql Server.
Первая SELECT
генерирует начальную строку (в этом случае "M", 1). Вторая SELECT
- это рекурсивная часть, которая генерирует последующие строки, причем столбец Pos
получает каждый раз, пока условие завершения WHERE Pos < LEN(@source)
не будет окончательно удовлетворено. Окончательный выбор удаляет дубликаты. Внутри SELECT DISTINCT
сортирует строки, чтобы облегчить удаление дубликатов, поэтому окончательный вывод происходит в алфавитном порядке. Поскольку вы не указали заказ как требование, я оставил его как есть. Но вы можете изменить его, чтобы вместо этого использовать GROUP
, упорядоченный по MIN(Pos)
, если вам нужен вывод в исходном порядке символов.
Эта же техника может использоваться для таких вещей, как генерация всех биграмм для строки, с небольшим изменением общей структуры выше.
Ответ 3
declare @charr varchar(99)
declare @lp int
set @charr='Manhattan'
set @lp=1
DECLARE @T1 TABLE (
FLD VARCHAR(max)
)
while(@lp<=LEN(@charr))
begin
if(not exists(select * from @T1 where FLD=(select SUBSTRING(@charr,@lp,1))))
begin
insert into @T1
select SUBSTRING(@charr,@lp,1)
end
set @[email protected]+1
end
select * from @T1
проверьте, что это может помочь u
Ответ 4
Здесь приведена версия Oracle @user2864740. Единственное различие заключается в том, как вы создаете "таблицу чисел" (плюс небольшие различия в псевдониме)
select letter
from (
select ns.n as pos, substr(ss.s, ns.n, 1) as letter
from (select 'MANHATTAN' as s from dual) ss
cross join (
SELECT LEVEL as n
FROM DUAL
CONNECT BY LEVEL <= 9
ORDER BY LEVEL) ns
) pairs
group by letter
order by min(pos)