Многократное обновление TSQL для одной и той же строки из отношения 1 к N - PullRequest
0 голосов
/ 08 мая 2018

У меня есть следующая таблица:

Message ID, Message, TextID, Text
1,'First name:{0}; Last name:{1}', 0, 'John'
1,'First name:{0}; Last name:{1}', 1, 'Doe'
2,'Address: {0}; City: {1}; Country: {2}',0,'Maple Str. 1'
2,'Address: {0}; City: {1}; Country: {2}',1,'New York'
2,'Address: {0}; City: {1}; Country: {2}',2,'USA'

Мне нужен запрос, который выбирает:

'First name: John; Last name: Doe'
'Address: Maple Str.1; City: New York; Country: USA'

Поскольку я заранее не знаю, сколько заполнителей содержится в каждом сообщении, я не могу сделать что-то вроде N соединений между таблицей и самим собой (если я не подсчитал, что максимальное количество заполнителей равно 20, а я - 20). присоединяйся но это ооочень ужасно!)

Есть ли что-то вроде рекурсивного CTE, который группирует строки по IDMessage и начинает обновлять Сообщение заменой?

1 Ответ

0 голосов
/ 08 мая 2018

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

IF OBJECT_ID('tempdb..#Message') IS NOT NULL
    DROP TABLE #Message

CREATE TABLE #Message (
    MessageID INT,
    Message VARCHAR(200))

INSERT INTO #Message (
    MessageID,
    Message)
VALUES
    (1, 'First name:{0}; Last name:{1}'),
    (2, 'Address: {0}; City: {1}; Country: {2}')

IF OBJECT_ID('tempdb..#Text') IS NOT NULL
    DROP TABLE #Text

CREATE TABLE #Text (
    MessageID INT,
    TextPlaceholder INT,
    Text VARCHAR(100)
    PRIMARY KEY (MessageID, TextPlaceholder))

INSERT INTO #Text (
    MessageID,
    TextPlaceholder,
    Text)
VALUES
    (1, 0, 'John'),
    (1, 1, 'Doe'),
    (2, 0, 'Maple Str. 1'),
    (2, 1, 'New York'),
    (2, 2, 'USA')


;WITH MaxPlaceholderByMessage AS
(
    SELECT
        M.MessageID,
        MaxPlaceholder = MAX(T.TextPlaceholder)
    FROM
        #Message AS M
        INNER JOIN #Text AS T ON M.MessageID = T.MessageID
    GROUP BY
        M.MessageID
),
 RecursiveReplacePlaceholders AS
(
    SELECT
        MessageID = M.MessageID,
        ReplacedMessage = CONVERT(VARCHAR(MAX), M.Message),
        CurrentPlaceholder = -1
    FROM
        #Message AS M

    UNION ALL

    SELECT
        MessageID = R.MessageID,
        ReplacedMessage = REPLACE(
            R.ReplacedMessage, 
            '{' + CONVERT(VARCHAR(10), T.TextPlaceholder) + '}',
            T.Text),
        CurrentPlaceholder = T.TextPlaceholder
    FROM
        RecursiveReplacePlaceholders AS R
        INNER JOIN #Text AS T ON
            R.MessageID = T.MessageID AND
            R.CurrentPlaceholder + 1 = T.TextPlaceholder
)
SELECT
    R.MessageID,
    R.ReplacedMessage
FROM
    RecursiveReplacePlaceholders AS R
    LEFT JOIN MaxPlaceholderByMessage AS M ON R.MessageID = M.MessageID
WHERE
    M.MaxPlaceholder = R.CurrentPlaceholder OR
    M.MessageID IS NULL -- There is no text available to replace
ORDER BY
    R.MessageID

/*
Result:

    MessageID   ReplacedMessage
    1           First name:John; Last name:Doe
    2           Address: Maple Str. 1; City: New York; Country: USA
*/

Если у вас отсутствуют тексты для заполнителя, вам придется немного изменить рекурсивное условие для циклического перехода до максимального доступного заполнителя.

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