Подтвердить что ты не робот

Как разделить и отобразить различные буквы из слова в SQL?

Вчера на собеседовании мне задали этот вопрос, и я понятия не имел об этом. Предположим, у меня есть слово "Манхэттен", я хочу отображать только буквы "M", "A", "N", "H", "T", в SQL. Как это сделать? Любая помощь приветствуется.

4b9b3361

Ответ 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)