Рекурсивный CTE SQL Server не возвращает ожидаемые строки - PullRequest
0 голосов
/ 24 апреля 2018

Я создаю марковский генератор имен цепей. Я пытаюсь заменить цикл while рекурсивным CTE. Ограничения в использовании top и order by в рекурсивной части CTE привели меня к следующему пути.

Смысл всего этого состоит в том, чтобы генерировать имена на основе модели, которая является еще одним словом, которое я разбил на три сегмента символов, хранящихся в трех столбцах таблицы Markov_Model. Следующим символом в последовательности будет символ из Markov_Model, так что 1-й и 2-й символы в модели соответствуют предпоследнему и последнему символу в генерируемом слове. Вместо того, чтобы генерировать матрицу вероятностей для этого третьего символа, я использую скалярную функцию, которая находит все символы, которые соответствуют критериям, и получает один из них случайным образом: order by newid().

Проблема в том, что эта формулировка CTE получает желаемое количество строк в сегменте привязки, но объединение, которое рекурсивно вызывает CTE, только union s на одну строку из привязки. Я прикрепил образец желаемого выхода внизу.

Запрос:

;with names as 
(
    select top 5
        cast('+' as nvarchar(50)) as char1,
        cast('+' as nvarchar(50)) as char2,
        cast(char3 as nvarchar(50)) as char3,
        cast('++' + char3 as nvarchar(100)) as name_in_progress,
        1 as iteration
    from markov_Model
    where char1 is null
        and char2 is null
    order by newid()                 -- Get some random starting characters

    union all

    select
        n.char2 as char1,
        n.char3 as char2,
        cast(fnc.addition as nvarchar(50)) as char3,
        cast(n.name_in_progress + fnc.addition as nvarchar(100)),
        1 + n.iteration 
    from names n
    cross apply (
        -- This function takes the preceding two characters, 
        -- and gets a random character that follows the pattern
        select isnull(dbo.[fn_markov_getNext] (n.char2, n.char3), ',') as addition
    ) fnc
)
select * 
from names
option (maxrecursion 3)          -- For debug

Проблема в том, что union только одна строка union.

Пример вывода:

char1   char2   char3   name_in_progress    iteration
+       +       F       ++F                 1
+       +       N       ++N                 1
+       +       K       ++K                 1
+       +       S       ++S                 1
+       +       B       ++B                 1
+       B       a       ++Ba                2
B       a       c       ++Bac               3
a       c       h       ++Bach              4

Примечание. Я использую + и , в качестве null заменителей / разделителей.

Я хочу увидеть всю предыдущую рекурсию с добавлением новых символов в name_in_progress; каждый проход должен полностью изменить предыдущий проход.

Мой желаемый результат будет:

enter image description here

Топ 10 таблицы Markov_Model:

enter image description here

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

CREATEFUNCTION [dbo].[fn_markov_getNext]
(
    @char2 nvarchar(1),
    @char3 nvarchar(1)
)
RETURNS nvarchar(1)
AS
BEGIN

    DECLARE @newChar nvarchar(1)

    set @newChar = (
        select top 1
            isnull(char3, ',')
        from markov_Model mm 
        where isnull(mm.char1, '+') = isnull(@char2, '+')
            and isnull(mm.char2, '+') = isnull(@char3, ',')
        order by (select new_id from vw_getGuid)    -- A view that calls newid()
    )

    return @newChar

END
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...