Есть ли функция для сортировки таблицы в MS Report Designer для строки типа xx.xx.x.xxx.x.xx?

#sql-server #visual-studio #reporting-services #columnsorting

#sql-server #visual-studio #службы отчетов #сортировка столбцов

Вопрос:

У меня есть отчет для спецификации, который получает так называемый «RowOrder» из SQL-запроса.

Отчет отображается правильно, но я хочу изменить сортировку строк:

фактическая сортировка строк

Если теперь есть порядок строк: 1, 2, 3, 4, 5, 3.1, 3.2, 3.3

Вместо этого мне нужен порядок строк: 1, 2, 3, 3.1, 3.2, 3.3, 4, 5

Как я могу этого добиться?

Информация спецификации поступает из Autodesk Vault SQL Server, и я редактирую ее с помощью MS Visual Studio 2015. Это отчет RDLC.

Комментарии:

1. Я думаю, самым простым способом было бы преобразовать все числа в десятичную дробь. Таким образом, это будет выглядеть как 1.0, 2.0, 3.0, 3.1 и т.д. Будет ли это приемлемым форматом? Если это так, вы можете просто умножить roworder на 1.0 ( select roworder * 1.0 )

2. Спасибо, НО: глубина вложенности не ограничивается 2 . Может быть, есть что-то вроде: 3.2.5.10.21.3. Это значение для одной строки.

3. Каков тип данных этого столбца roworder?

4. Я полагаю, это строка.

5. Я был бы очень удивлен, если бы это была строка, но, тем не менее, я смог получить требуемый порядок, используя ПРИВЕДЕНИЕ для преобразования этого столбца в тип данных с плавающей запятой.

Ответ №1:

Это сработало для меня. Выполнение простого выбора показывает, что порядок отключен, но при добавлении ORDER BY 1 он упорядочивается так, как вы ищете.

 CREATE TABLE #test(row FLOAT)

INSERT INTO #test
VALUES(1), (2), (2.2), (2.3), (4), (3)

SELECT *
FROM #test
ORDER BY 1
 

Таким образом, решением было бы изменить ваш запрос, чтобы изменить тип данных.

 CAST(RowOrder as float)
 

Ответ №2:

Я написал функцию для аналогичной задачи, которая преобразует точечную нотацию в bigint, которую затем можно сортировать. Ожидаемые части и максимальная длина детали должны быть установлены на значения как можно меньшие, хотя функция может обрабатывать номер детали 3, даже если вы говорите, что ожидаемые части равны 4 (это просто добавит больше нулей).

Эта функция завершится ошибкой, если будет много длинных частей, но для моих целей она работала нормально. Если у вас не получается, вы можете изменить ее, чтобы возвращать строковое значение вместо приведения его к bigint (последняя строка кода).

обратите внимание, что при этом используется функция разделения (код также прилагается). Я не уверен, что вы могли бы использовать вместо этого функцию SQL2016> string_split, но я написал это много лет назад.


[fn] .[ConvertDotNotationToInteger] код


 CREATE FUNCTION [fn].[ConvertDotNotationToInteger] (@dotNumber varchar(256), @expectedParts int = 4, @MaxPartLength int = 4)
RETURNS bigint 
AS
BEGIN

-- if @dotNumber contains less parts than the expected number append '.0' to the end
declare @foundParts bigint
WHILE (SELECT COUNT(*) FROM fn.split(@dotNumber, '.')) < @expectedParts
    BEGIN
        SET @dotNumber = @dotNumber   '.00'
    END

declare @rStr varchar(256) = ''
SELECT @rstr = @rstr   right('00000000'  rtrim(value), @MaxPartLength) from fn.split(@dotNumber, '.')

RETURN cast(@rStr as bigint)

END
 

fn.split t-sql код


 CREATE  FUNCTION [fn].[Split](@sText varchar(8000), @sDelim varchar(20) = ' ')
RETURNS @retArray TABLE (idx smallint Primary Key, value varchar(8000))
AS
BEGIN
DECLARE @idx smallint,
    @value varchar(8000),
    @bcontinue bit,
    @iStrike smallint,
    @iDelimlength tinyint
IF @sDelim = 'Space'
    BEGIN
    SET @sDelim = ' '
    END
SET @idx = 0
SET @sText = LTrim(RTrim(@sText))
SET @iDelimlength = DATALENGTH(@sDelim)
SET @bcontinue = 1
IF NOT ((@iDelimlength = 0) or (@sDelim = 'Empty'))
    BEGIN
    WHILE @bcontinue = 1
        BEGIN
--If you can find the delimiter in the text, retrieve the first element and
--insert it with its index into the return table.
 
        IF CHARINDEX(@sDelim, @sText)>0
            BEGIN
            SET @value = SUBSTRING(@sText,1, CHARINDEX(@sDelim,@sText)-1)
                BEGIN
                INSERT @retArray (idx, value)
                VALUES (@idx, @value)
                END
            
--Trim the element and its delimiter from the front of the string.
            --Increment the index and loop.
SET @iStrike = DATALENGTH(@value)   @iDelimlength
            SET @idx = @idx   1
            SET @sText = LTrim(Right(@sText,DATALENGTH(@sText) - @iStrike))
        
            END
        ELSE
            BEGIN
--If you can't find the delimiter in the text, @sText is the last value in
--@retArray.
 SET @value = @sText
                BEGIN
                INSERT @retArray (idx, value)
                VALUES (@idx, @value)
                END
            --Exit the WHILE loop.
SET @bcontinue = 0
            END
        END
    END
ELSE
    BEGIN
    WHILE @bcontinue=1
        BEGIN
        --If the delimiter is an empty string, check for remaining text
        --instead of a delimiter. Insert the first character into the
        --retArray table. Trim the character from the front of the string.
--Increment the index and loop.
        IF DATALENGTH(@sText)>1
            BEGIN
            SET @value = SUBSTRING(@sText,1,1)
                BEGIN
                INSERT @retArray (idx, value)
                VALUES (@idx, @value)
                END
            SET @idx = @idx 1
            SET @sText = SUBSTRING(@sText,2,DATALENGTH(@sText)-1)
            
            END
        ELSE
            BEGIN
            --One character remains.
            --Insert the character, and exit the WHILE loop.
            INSERT @retArray (idx, value)
            VALUES (@idx, @sText)
            SET @bcontinue = 0  
            END
    END
END
RETURN
END
 

Ответ №3:

вам нужна явная функция преобразования строк для выражения порядка, подобного этому:

=CStr(поля!rowOrder.Value)

выражение порядка отчета