Получение данных каждой строки и установка их в переменную - TSQL - PullRequest
0 голосов
/ 27 марта 2019

Я пытаюсь создать цикл, который будет извлекать одно значение строки и сохранять его в переменной (@nameString). Мне нужно, чтобы это произошло для неизвестного количества строк. На что я должен ссылаться, когда мне нужно, чтобы этот цикл циклически проходил по всем строкам и обновлял мою переменную каждый раз, когда она повторяется со значением следующих строк.

Я пробовал несколько встречных циклов, и они не циклически перебирают строки, они просто продолжают попадать в один и тот же.

-- Code for parsing a name with multiple parts

DECLARE     @nameString as varchar(max),
            @firstSpaceLoc as smallint,
            @secondSpaceLoc as smallint,
            @thirdSpaceLoc as smallint,
            @firstString as varchar(max),
            @secondString as varchar(max),
            @thirdString as varchar(max) 

-- I'm expecting the loop to be below here!
SET @nameString = 'Robert Dobson, Jr.'
--SET @nameString = 'Robert William Dobson, Sr.'

-- How many strings are in the name?
-- Is there one space in the name
SET @firstSpaceLoc = CHARINDEX(' ',@namestring,1)

-- Is there second space in the name
SET @secondSpaceLoc = CHARINDEX(' ', @namestring, CHARINDEX('     ',@nameString,1)+1)

-- Is there a third space in the name
SET @thirdSpaceLoc = 
CASE
      WHEN CHARINDEX(' ', @namestring, 
           CHARINDEX(' ',@nameString,1)+1) = 0 THEN 0
      WHEN CHARINDEX(' ', @namestring, 
           CHARINDEX(' ',@nameString,1)+1) > 0 THEN
           CHARINDEX(' ', @namestring, 
           CHARINDEX(' ', @namestring, 
           CHARINDEX(' ',@nameString,1)+1)+1)
END

SELECT
            @nameString sourceString,
            CASE 
                        WHEN @firstSpaceLoc > 0 THEN 'There is one space'
                        ELSE 'There is not one space'
            END [Is there one space],
            CASE 
                        WHEN @secondSpaceLoc > 0 THEN 'There is a second     space'
                        ELSE 'There is not a second space'
            END [Is there a second space],
            CASE 
                        WHEN @thirdSpaceLoc > 0 THEN 'There is a third space'
                        ELSE 'There is not a third space'
            END [Is there a third space]


-- extract and save strings
SELECT

@firstString = 
       CASE
            WHEN @firstSpaceLoc > 0 THEN LEFT(@nameString,CHARINDEX('     ',@namestring,1)-1)
            ELSE @nameString
       END,
       @secondString =   
       CASE
            WHEN @firstSpaceLoc = 0 THEN ''
            WHEN @secondSpaceLoc = 0 THEN 
                        RIGHT(@namestring, LEN(@namestring)- CHARINDEX('     ',@namestring,1))
            WHEN @secondSpaceLoc > 0 THEN
                        REPLACE     (
                        SUBSTRING   (
                                       @nameString, 
                                       CHARINDEX(' ',@namestring,1)+1, 
                                       CHARINDEX(' ', @namestring, 
                                       CHARINDEX(' ',@nameString,1)+1) 
                                             - CHARINDEX(' ',@namestring,1)
                                     ),
                                     ',',
                                     ''
                                     )
            ELSE ''
      END,
      @thirdString =
      CASE
            WHEN @firstSpaceLoc = 0 OR @secondSpaceLoc = 0  THEN ''
            WHEN @secondSpaceLoc > 0 
                        AND @thirdSpaceLoc = 0 THEN
                        SUBSTRING   (
                                       @nameString,
                                       CHARINDEX(' ', @namestring, 
                                       CHARINDEX(' ',@nameString,1)+1)+1,
                                       LEN(@nameString)
                                     )     
            ELSE RIGHT(@namestring,LEN(@namestring) - @secondSpaceLoc)              
      END


-- Report names
SELECT
            @nameString sourceString,
            @firstString [First string],
            @secondString [Second string],
            @thirdString [Third string]

SELECT
        CASE
                  WHEN @thirdSpaceLoc > 0 THEN 
                                    @thirdString + ', '  + @firstString + ' '     + @secondString
                  WHEN @secondSpaceLoc > 0 AND @thirdSpaceLoc = 0 THEN 
                                    @secondString + ' '  + @thirdString + ',     ' + @firstString
                  WHEN @firstSpaceLoc > 0 THEN 
                                    @secondString + ', '  + @firstString 
                  WHEN @firstSpaceLoc = 0 THEN 
                                    @firstString
            END [Reported Name]

Ожидаемые результаты: все строки столбца с несколькими пробелами разделяются на длинный список имен, разделенных. Этот список, но гораздо больше. enter image description here

Ответы [ 3 ]

0 голосов
/ 27 марта 2019

Извините, если в коде есть какая-то ошибка, у меня нет доступа к MS-SQL, сейчас я попытался закодировать прямо здесь. Ваш запрос довольно необычный (я согласен с комментарием Роберта), но такой простой код будет работать.

DECLARE    @nameString as varchar(max),
           @firstString as varchar(max),
           @secondString as varchar(max),
           @thirdString as varchar(max)

SET @nameString = 'Robert Dobson, Jr.'

SET @thirdString = REPLACE(@nameString, ',', '')
SET @firstString = LTRIM(SUBSTRING(@thirdString, 1, CHARINDEX(' ', @thirdString)))
SET @thirdString = LTRIM(REPLACE(@thirdString, @firstString, ‘’))
SET @secondString = LTRIM(SUBSTRING(@thirdString, 1, CHARINDEX(' ', @thirdString)))
SET @thirdString = LTRIM(REPLACE(@thirdString, @secondString, ‘’))

SELECT
            @nameString sourceString,
            @firstString [First string],
            @secondString [Second string],
            @thirdString [Third string]
0 голосов
/ 27 марта 2019

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

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

create View [dbo].[cteTally] as

WITH
    E1(N) AS (select 1 from (values (1),(1),(1),(1),(1),(1),(1),(1),(1),(1))dt(n)),
    E2(N) AS (SELECT 1 FROM E1 a, E1 b), --10E+2 or 100 rows
    E4(N) AS (SELECT 1 FROM E2 a, E2 b), --10E+4 or 10,000 rows max
    cteTally(N) AS 
    (
        SELECT  ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM E4
    )
select N from cteTally

Следующее, что нам нужно, это разделитель строк.Существует несколько таких программ, и даже встроенный в последние версии сервера SQL.Тем не менее, даже MS не хватает критического элемента порядкового положения для каждого элемента.К счастью, у Джеффа Модена есть тот, который настроен на основе, молниеносно и возвращает номер позиции каждого элемента.

Вы можете найти код для DelimitedSplit8K здесь .

Сейчасмы сталкиваемся с проблемой возврата динамического числа столбцов.Для этого вы можете использовать динамический пивот.Это будет работать просто отлично.Для меня я нахожу синтаксис для pivot очень тупым и предпочитаю использовать условную агрегацию или перекрестную таблицу.В этом случае он должен быть динамическим.

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

if OBJECT_ID('tempdb..#Something') is not null
    drop table #Something

create table #Something --this represents your current table
(
    nameString varchar(100)
)

insert #Something values
('Robert Dobson, Jr.')
, ('NeoAer')
, ('Ryan Wilson')
, ('Somebody with four names')
, ('another with yet more names')

declare @StaticPortion nvarchar(2000) = 
    'with OrderedResults as
    (
        select nameString
            , stringValue = replace(x.Item, '','', '''')
            , x.ItemNumber
        from #Something s
        cross apply dbo.DelimitedSplit8K(s.nameString, '' '') x
    )
    select nameString';

declare @DynamicPortion nvarchar(max) = '';
declare @FinalStaticPortion nvarchar(2000) = ' from OrderedResults Group by nameString order by nameString';

select @DynamicPortion = @DynamicPortion + 
    ', MAX(Case when ItemNumber = ' + CAST(N as varchar(6)) + ' then stringValue end) as string' + CAST(N as varchar(6)) + CHAR(10)
from cteTally t
where t.N <= 
(
    select top 1 Count(*)
    from #Something s
    cross apply dbo.DelimitedSplit8K(s.nameString, ' ') x
    group by nameString
    order by COUNT(*) desc
)

select @StaticPortion + @DynamicPortion + @FinalStaticPortion

--once you are satisfied that the dynamic sql is correct uncomment the next two lines to execute it.
--declare @SqlToExecute nvarchar(max) = @StaticPortion + @DynamicPortion + @FinalStaticPortion;
--exec sp_executesql @SqlToExecute

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

0 голосов
/ 27 марта 2019

Вы можете попробовать вот так:

DECLARE     @nameString AS VARCHAR(MAX),                
            @firstString AS VARCHAR(MAX),
            @secondString AS VARCHAR(MAX),
            @thirdString AS VARCHAR(MAX) 

SET @nameString = 'Robert Dobson, Jr.'

DECLARE @tbl TABLE
(
    Id INT IDENTITY(1,1),
    Name VARCHAR(MAX)
)

INSERT INTO @tbl(Name)
SELECT value FROM STRING_SPLIT(@nameString, ' ');


SELECT @firstString = Name FROM @tbl WHERE Id = 1
SELECT @secondString = Name FROM @tbl WHERE Id = 2
SELECT @thirdString = Name FROM @tbl WHERE Id = 3


SELECT
@nameString sourceString,
CASE WHEN LEN(@firstString) > 0 THEN 'There is one space'
            ELSE 'There is not one space'
END [Is there one space],
CASE WHEN LEN(@secondString)> 0 THEN 'There is a second     space'
            ELSE 'There is not a second space'
END [Is there a second space],
CASE WHEN LEN(@thirdString)> 0 THEN 'There is a third space'
            ELSE 'There is not a third space'
END [Is there a third space]

SELECT @nameString SourceString, @firstString [First string], @secondString [Second string] , @thirdString [Third string]

SELECT
    CASE
        WHEN LEN(@thirdString) > 0 THEN 
                        @thirdString + ', '  + @firstString + ' '     + @secondString
        WHEN LEN(@secondString) > 0 AND LEN(@thirdString) = 0 THEN 
                        @secondString + ' '  + @thirdString + ',     ' + @firstString
        WHEN LEN(@firstString) > 0 THEN 
                        @secondString + ', '  + @firstString 
        WHEN LEN(@firstString) = 0 THEN 
                        @firstString
        END [Reported Name]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...