Получить все перестановки значений k (k = 1 ... n) - PullRequest
2 голосов
/ 23 ноября 2011

Мне нужен запрос, который можно использовать в (или в качестве) функции и получить все перестановки n значений. И мне нужны все перестановки длины k, где k = 1.n. ​​

РЕДАКТИРОВАТЬ # 1: расширенный выборочный ввод и результат, так что ввод имеет 3 значения вместо 2 - однако количество входных значений может варьироваться от 1 до n.

Пример:

Ввод: таблица со значениями в одном столбце в нескольких строках

    Value  (nvarchar(500))
    ------
    Ann
    John
    Mark

Редактировать # 2: я могу жить с любым из следующих выходов

Вывод № 1: таблица со значениями, объединенными в один столбец

    Ann
    John
    Ann,John
    John,Ann
    Ann,Mark
    Mark,Ann
    John,Mark
    Mark,John
    Ann,John,Mark
    Ann,Mark,John
    John,Ann,Mark
    John,Mark,Ann
    Mark,Ann,John
    Mark,John,Ann

Вывод № 2: таблица с идентификатором перестановки / комбинации, значения и порядка

    id    value    order
    --------------------
    1     Ann      1
    2     John     1
    3     Ann      1
    3     John     2
    4     John     1
    5     Ann      2

Примечания:

  • должен работать на SQL Server 2008 R2
  • должен работать в функции
  • максимальное количество ожидаемых отдельных элементов на входе никогда не должно превышать 5 - если это важно для производительности или по любой другой причине
  • Столбец значений во входной таблице не может превышать 200 символов в длину - если это имеет значение для производительности или по любой другой причине

После долгих поисков в Интернете я обнаружил Создание перестановок в ветке форума T-SQL , но мне не удалось изменить его, чтобы получить ожидаемый формат вывода и заставить его сделать k = 1 ... n перестановок также.

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

1 Ответ

8 голосов
/ 23 ноября 2011
;WITH Names(Name) As
(
SELECT 'Ann' UNION ALL
SELECT 'John' UNION ALL
SELECT 'Mark' 
), R(Name,Lvl) AS
(
SELECT CAST(',' + Name AS VARCHAR(MAX)), 1
FROM Names
UNION ALL
SELECT R.Name + ',' + N.Name, Lvl + 1
FROM R JOIN Names N ON R.Name + ',' NOT LIKE '%,' + N.Name + ',%'
)
SELECT STUFF(Name,1,1,'') AS Name
FROM R
ORDER BY Lvl, Name

Возвращает

Name
------------------------------
Ann
John
Mark
Ann,John
Ann,Mark
John,Ann
John,Mark
Mark,Ann
Mark,John
Ann,John,Mark
Ann,Mark,John
John,Ann,Mark
John,Mark,Ann
Mark,Ann,John
Mark,John,Ann
...