IIF или CASE в запросе объединения - PullRequest
0 голосов
/ 30 апреля 2018

У меня есть следующий запрос, который является частью функции скалярной переменной, но я получаю тот же результат, пытаясь выполнить запрос, поэтому кажется, что проблема в конкатенации и / или использовании переменной.

DECLARE @useCompTitle BIT
SET @useCompTitle = (SELECT z.useComplianceTitle FROM dbo.tblConfiguration z WHERE z.id = 1)
DECLARE @Output as VARCHAR(MAX) = '';
DECLARE @ReturnValue as VARCHAR(MAX)='';
SELECT @Output = @Output + 
                '<tr><td style="vertical-align:top">' + 
                p.ProcessNumber + 
                '</td><td>' + 
                (IIF(@useCompTitle = 0, p.Process, p.title)) + 
                '</td><td style="vertical-align:top">' + 
                CASE p.recordStatus 
                    WHEN 1 THEN N'Active' 
                    WHEN 2 THEN N'Inactive' 
                END  + 
                '</td></tr>'
FROM dbo.tblProcess p
CROSS JOIN dbo.Security_Compliance_Record_List(1, 0, 0) AS p1
INNER JOIN dbo.tblERLinkedRecords l ON p.id = l.recID
WHERE l.eventID = 1172 
AND l.linkType = 'C' 
AND p.id = p1.id 
AND p.recordStatus < 3
ORDER BY p.ProcessNumber
PRINT @OutputThe result should return multiple values in @Output but I am only getting the last record in the set.

Я также пробовал оператор CASE с тем же результатом. Если я заменю IIF (или CASE) простым именем поля, я получу правильное количество значений. CASE для p.RecordStatus работает правильно, если IIF заменяется простым значением поля (например, p.title). Мы используем процесс @useCompTitle во многих хранимых процедурах, но это первый раз в запросе объединения.

Ответы [ 3 ]

0 голосов
/ 30 апреля 2018

Использование IIF и CONCAT

Демо

declare @mytable table (processnumber int, recordstatus smallint,process varchar(20), title varchar(20))

insert into @mytable 
values 
(1,1,'Proc1','Title1'),
(2,2,'Proc2','Title2'),
(3,1,'Proc3','Title3'),
(4,2,'Proc4','Title4'),
(5,1,'Proc5','Title5')



DECLARE @useCompTitle BIT
SET @useCompTitle = 1
DECLARE @Output as VARCHAR(MAX) = '';
DECLARE @ReturnValue as VARCHAR(MAX)='';

SELECT @Output = concat(@Output, 
                '<tr><td style="vertical-align:top">', 
                p.ProcessNumber,
                '</td><td>', 
                IIF(@useCompTitle = 0, p.Process, p.title),     -- as per @useCompTitle will always display Title when 1
                '</td><td style="vertical-align:top">',
                IIF( p.recordStatus  = 1,'Active','Inactive' ),
                '</td></tr>') 
from @mytable p


print  @Output
0 голосов
/ 30 апреля 2018

Спасибо за все комментарии. После еще одного тестирования я обнаружил, что проблема была в ORDER BY и известной проблеме . Это отличная статья. Я решил проблему, изменив функцию в соответствии с предложением, и все работает правильно.

  CREATE FUNCTION [dbo].[CR_Events_Linked_Compliance] 

( @ параметр1 INT, @ parameter2 BIT = 0, @recID INT, @useCompTitle BIT ) ВОЗВРАЩАЕТСЯ ВАРЧАР (МАКС) КАК НАЧАТЬ ОБЪЯВИТЬ @ Output as VARCHAR (MAX) = ''; ОБЪЯВИТЬ @ReturnValue как VARCHAR (MAX) = ''; SELECT @Output = (SELECT '' + p.ProcessNumber + '' + IIF (@useCompTitle = 0, p.Process, p.title) + '' + IIF (p.recordStatus = 1, 'Active', 'Inactive' ) + '' FROM dbo.tblProcess p CROSS JOIN dbo.Security_Compliance_Record_List (@ параметр1, @ параметр2, 0) AS p1 ВНУТРЕННЕЕ СОЕДИНЕНИЕ dbo.tblERLinkedRecords l ON p.id = l.recID ГДЕ l.eventID = @recID AND l.linkType = 'C' AND p.id = p1.id AND p.recordStatus <3 ORDER BY p.ProcessNumber ДЛЯ ПУТИ XML (''), ТИП ) .Value ( ' '' VARCHAR (макс)') IF @Output = '' SET @ReturnValue = '' еще SET @ReturnValue = '<strong> Число Процесс Статус ' + @Output + '' RETURN @ReturnValue END

0 голосов
/ 30 апреля 2018

Если запрос возвращает одну строку, SQL Server сохраняет это значение в переменной. Однако, если есть несколько строк, это не имеет смысла. Переменная содержит одно значение, но в нем можно хранить несколько значений. Это может привести к ошибке, но Microsoft решила, что она просто сохранит последнее значение. Вполне возможно, что он мог сохранить и первое, но это не то, что они решили. В целом, на это поведение нельзя положиться, поскольку оно не является разумным с точки зрения семантики.

На самом деле, я думаю, что это то, где вы попадаете в ловушку. Хотя можно думать, что запрос имеет цикл for для таблиц и строк, на самом деле это не так. Это серия операций над наборами кортежей (строк). Концептуально, результатом является один набор строк, которые «прибывают» одновременно. Там нет порядка выполнения строк (больше, чем есть порядок выполнения только что существующего массива). Таким образом, в этом нет никакого смысла.

Теперь то, что вы хотите достичь , само по себе разумно. Вы хотите, чтобы строка была построена путем конкатенации результатов запроса, который возвращает несколько строк. Представьте, что у вас есть более простой запрос, в котором вы просто хотите суммировать некоторые числа вместо объединения строк. Вы бы просто использовали агрегат SUM(), потенциально с предложением GROUP BY. Результат этого может быть сохранен в переменную. Поскольку агрегация сделает так, что в наборе результатов будет только одна строка, вам не нужно беспокоиться о том, какая строка сохраняет значение. Агрегация строк работает аналогично. За исключением ... SQL Server не имел операции STRING_SUM() до SQL Server 2017. Тем не менее, есть способы сделать это во всех версиях SQL Server. Вы можете использовать трюк XML или написать свою собственную функцию агрегирования (на языке .NET). См. Мне нужно написать запрос типа group_concat в SQL Server , чтобы узнать, как это сделать.

Надеюсь, этого достаточно, чтобы вы пошли!

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