SQL Server SELECT STUFF возвращает неправильные значения - PullRequest
2 голосов
/ 22 апреля 2019

Я использовал STUFF в прошлом и без проблем, но этот немного другой. Возможно из-за структуры таблицы. Я создал хороший сценарий тестирования, если кто-то захочет взглянуть на него. Любой вклад приветствуется.

DECLARE @DetailTbl TABLE(DetailID INT IDENTITY(1,1) NOT NULL, Roll VARCHAR(6))
INSERT INTO @DetailTbl (Roll) VALUES ('ABC')
INSERT INTO @DetailTbl (Roll) VALUES ('DEF')
INSERT INTO @DetailTbl (Roll) VALUES ('JKL')
INSERT INTO @DetailTbl (Roll) VALUES ('MNO')

DECLARE @RunTbl TABLE(ID INT IDENTITY(1,1) NOT NULL, Run VARCHAR(6))
INSERT INTO @RunTbl (Run) VALUES ('X12')
INSERT INTO @RunTbl (Run) VALUES ('Y34')
INSERT INTO @RunTbl (Run) VALUES ('Z56')

DECLARE @RunRollRef TABLE(ID INT IDENTITY(1,1) NOT NULL, RunID INT, DetailID INT)
INSERT INTO @RunRollRef (RunID, DetailID) VALUES (1, 1)
INSERT INTO @RunRollRef (RunID, DetailID) VALUES (1, 2)
INSERT INTO @RunRollRef (RunID, DetailID) VALUES (1, 3)
INSERT INTO @RunRollRef (RunID, DetailID) VALUES (2, 4)
INSERT INTO @RunRollRef (RunID, DetailID) VALUES (2, 1)
INSERT INTO @RunRollRef (RunID, DetailID) VALUES (3, 2)
INSERT INTO @RunRollRef (RunID, DetailID) VALUES (3, 3)

SELECT rt.ID,

(SELECT
STUFF((SELECT dt.Roll + ','
FROM @DetailTbl dt
INNER JOIN @RunRollRef ref ON ref.DetailID = dt.DetailID
WHERE dt.DetailID = r.DetailID
FOR XML PATH(''), TYPE).value('.','VARCHAR(MAX)'), 1, 0, '')) 
AS Rolls

FROM @RunTbl rt
INNER JOIN @RunRollRef r ON r.RunID = rt.ID

--Expected Output
--1 ABC,DEF,JKL,
--2 MNO,ABC,
--3 DEF,JKL,

Ответы [ 2 ]

2 голосов
/ 22 апреля 2019

Я думаю, у вас слишком много объединений и вы не удаляете разделитель правильно. Попробуйте это:

SELECT rt.ID,
       (SELECT STUFF((SELECT ',' + dt.Roll
                      FROM @DetailTbl dt JOIN
                           @RunRollRef ref
                           ON ref.DetailID = dt.DetailID
                      WHERE ref.RunID = rt.ID
                      FOR XML PATH(''), TYPE
                     ).value('.', 'VARCHAR(MAX)'
                            ), 1, 1, '')
                    ) AS Rolls
FROM @RunTbl rt;

Обратите внимание на изменения:

  • Вам не нужно JOIN во внешнем запросе.
  • ',' - это с добавлением без последующей обработки.
  • Необходимо исправить условие корреляции в подзапросе.
  • Третий аргумент stuff() должен быть 1, а не 0. (Замена символов без пустой строки ничего не делает.)
2 голосов
/ 22 апреля 2019

Я бы использовал APPLY:

select rt.ID, stuff(tt.Rolls, 1, 1, '') as Rolls
from @RunTbl rt outer apply
     ( select ', '+dt.Roll
       from @RunRollRef rf inner join
            @DetailTbl dt
            on dt.DetailID = rf.DetailID
       where rf.RunID = rt.ID
       for xml path('')
     ) tt(Rolls);

Внешний select имеет ненужные JOIN с, которые действительно не нужны.

В подзапросе необходимо указать ref.RunID = rt.ID вместо dt.DetailID = r.DetailID.

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