Оптимизированный альтернативный код для функции обратного ввода строки слово в слово в SQL SERVER - PullRequest
0 голосов
/ 02 июля 2018
alter FUNCTION FlipName(@input VARCHAR(250))
RETURNS VARCHAR(250)

AS BEGIN

DECLARE @i int ,@add varchar(255)
set @i=1
set @add=''
declare @work varchar(250)
set @work=''
WHILE @i <= len(@input)
BEGIN
  declare @pivot varchar(255)
  set @pivot=SUBSTRING(@input,@i,1)
  while @pivot <>' '
  begin
     set @add=@add+@pivot
     set @i=@i+1
     set @pivot=SUBSTRING(@input,@i,1)
  end

  set @work=@add+' '+@work 
  set @add=''

  SET @i = @i + 1

END
return @work
END

Пример ввода: меня зовут Джарвис

Пример вывода: Джарвис зовут Мой

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

Я ищу лучший обходной путь без петель, может быть

Пожалуйста, дайте краткое объяснение вашему решению, указав, как оно лучше.

Заранее спасибо

Ответы [ 5 ]

0 голосов
/ 02 июля 2018

и еще один ... Следующий подход полностью встроен и использует таблицу подсчета на лету в связи со способностью XML извлекать элемент по его позиции:

DECLARE @input VARCHAR(100)='My name is Jarvis';

WITH Casted(inputXml) AS
(
    SELECT CAST('<x>' + REPLACE((SELECT @input AS [*] FOR XML PATH('')),' ','</x><x>') + '</x>' AS XML)
)
,Tally(Nmbr) AS
(
    SELECT TOP(SELECT inputXml.value('count(/x)','int') FROM Casted) ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) FROM master..spt_values
)
SELECT STUFF(
(
    SELECT ' ' + c.inputXml.value('(/x[sql:column("t.Nmbr")]/text())[1]','varchar(100)')
    FROM Tally t
    CROSS JOIN Casted c
    ORDER BY t.Nmbr DESC
    FOR XML PATH(''),TYPE).value('.','varchar(max)'
),1,1,'');
0 голосов
/ 02 июля 2018

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

CREATE FUNCTION [dbo].[fn_ReverseWordsInSentence]
(
    @ip VARCHAR(MAX)
)
RETURNS VARCHAR(MAX)

BEGIN
    DECLARE @op VARCHAR(MAX)
    SET @op = ''
    DECLARE @Lenght INT

    WHILE LEN(@ip) > 0
    BEGIN
        IF CHARINDEX(' ', @ip) > 0
        BEGIN
        SET @op = SUBSTRING(@ip,0,CHARINDEX(' ', @ip)) + ' ' + @op
        SET @ip = LTRIM(RTRIM(SUBSTRING(@ip,CHARINDEX(' ', @ip) + 1,LEN(@ip))))
    END
    ELSE
        BEGIN
        SET @op = @ip + ' ' + @op
        SET @ip = ''
        END
    END
RETURN @op
END

Вы выполняете эту функцию с указанной вами входной строкой следующим образом.

SELECT [dbo].[fn_ReverseWordsInSentence] ('My name is Jarvis')

И это вернет следующую строку в качестве вывода.

"Джарвис зовут Мой"

Если вы просто хотите перевернуть всю строку символ за символом, тогда вы можете использовать Sql Server во встроенной функции обратной строки.

DECLARE @test varchar(250) = 'My name is Jarvis'

SELECT reverse(@test)

И это вернет "sivraJ si eman yM" в качестве вывода.

0 голосов
/ 02 июля 2018

Учитывая, что здесь важна порядковая позиция (то, что STRING_SPLIT не возвращает), и что STRING_SPLIT и STRING_AGG - более недавно добавленная функция, вы можете использовать delimitedsplit8k и FOR XML PATH. Это означает, что порядок гарантирован (так как delimitedsplit8k возвращает порядковый номер), и это означает, что вам не нужен SQL Server 2017:

USE Sandbox;
GO

CREATE FUNCTION dbo.ReverseString_fn (@input varchar(255))
RETURNS table AS
RETURN

    SELECT STUFF((SELECT ' ' + DS.Item
                  FROM dbo.DelimitedSplit8K(@input,' ') DS
                  ORDER BY DS.ItemNumber DESC
                  FOR XML PATH('')),1,1,'') AS ReverseString;
GO

WITH VTE AS (
    SELECT 'My name is Jarvis' AS String)
SELECT *
FROM VTE V
     CROSS APPLY dbo.ReverseString_fn(V.String) RS;
GO

DROP FUNCTION dbo.ReverseString_fn;
0 голосов
/ 02 июля 2018

Я не предлагаю делать это в бэкэнде. Но для обхода ( ниже SQL Server 2016 ) у вас может быть код ниже. Вы можете создать функцию с помощью приведенного ниже кода и вызвать ее в строках таблицы.

DECLARE @VAL VARCHAR(MAX) ='My name is Jarvis', @NEW_VAL VARCHAR(MAX)='';

SELECT @VAL = '<M>'+ REPLACE(@VAL, ' ','</M><M>')+'</M>';

SELECT @NEW_VAL = @NEW_VAL+ ' ' + NEW_TEXT FROM ( 
SELECT ROW_NUMBER() OVER(ORDER BY(SELECT 1)) SNO, 
 splt.x.value('.','varchar(100)') NEW_TEXT FROM (
SELECT CAST(@VAL AS XML) AS DATA
)AS A
CROSS APPLY DATA.nodes('/M') as splt(x)
)B
ORDER BY SNO DESC;

SELECT @NEW_VAL

Результат:

 Jarvis is name My
0 голосов
/ 02 июля 2018

T-SQL - не лучшее решение для работы со строками. Но это можно сделать вообще без цикла (SQL Server 2017 +):

DECLARE @s NVARCHAR(MAX) = N'My name is Jarvis';

SELECT @s, STRING_AGG(value, ' ') WITHIN GROUP(ORDER BY rn DESC)
FROM (SELECT *, ROW_NUMBER() OVER(ORDER BY 1/0)AS rn
      FROM STRING_SPLIT(REPLACE(@s, ' ', '.'), '.'))s;

Демоверсия DBFiddle

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