Как инвертировать слова в столбце - PullRequest
0 голосов
/ 15 апреля 2009

У меня есть таблица со столбцом varchar (128) с такими данными, как:

слово1, слово2, слово3, слово4
слово1, слово2, слово3,,
word1 ,,,,; word2
; слово1 слово2, слово3

Я должен обновить эту таблицу, сделав слова обратного порядка:

word4,, word3,, word2, word1
,, word3,, word2, word1

Не могли бы вы помочь мне сделать это, используя только один SQL-запрос ??

Ответы [ 5 ]

2 голосов
/ 16 апреля 2009

Для выполнения этой задачи потребуются функция t-sql и курсор. fn_SplitList позволит вам разделить на основе разделителя. Если у вас есть эта функция, вы можете создать курсор, который будет работать с вашими данными, обновляя каждую запись. Я создал пример, используя @ table1.

Функция

CREATE FUNCTION [dbo].[fn_SplitList]
(
    @RowData varchar(8000),
    @SplitOn varchar(5)
)  
RETURNS @RtnValue table 
(
    Id int identity(1,1),
    Data varchar(100)
) 
AS  
BEGIN 
    Declare @Cnt int
    Set @Cnt = 1

    While (Charindex(@SplitOn,@RowData)>0)
    Begin
        Insert Into @RtnValue (data)
        Select 
            Data = ltrim(rtrim(Substring(@RowData,1,Charindex(@SplitOn,@RowData)-1)))

        Set @RowData = Substring(@RowData,Charindex(@SplitOn,@RowData)+1,len(@RowData))
        Set @Cnt = @Cnt + 1
    End

    Insert Into @RtnValue (data)
    Select Data = ltrim(rtrim(@RowData))

    Return
END

Код для обновления

declare @table1 table(id int primary key
                     ,words varchar(max))
declare @id int
declare @words varchar(max)

insert into @table1 values(0, 'word1, word2, , word3, word4')
insert into @table1 values(1, 'word1, word2, word3, ,')
insert into @table1 values(2, 'word1,,,, ; word2')
insert into @table1 values(3, ';word1 word2, word3')

declare updateCursor cursor for
select id
      ,words
  from @table1

open updateCursor   
fetch next from updateCursor into @id, @words
while @@fetch_status = 0
begin
  declare @row varchar(255)

  select @row = coalesce(@row+', ', '') + data
    from dbo.fn_SplitList(@words, ',')
  order by id desc

  update @table1
     set words = @row
   where id = @id

  fetch next from updateCursor into @id, @words
end
close updateCursor   
deallocate updateCursor

select *
  from @table1
1 голос
/ 16 апреля 2009

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

0 голосов
/ 16 апреля 2009

У меня есть мысль, так как вы ограничены одним запросом. Можете ли вы создать табличную UDF, которая будет делать то же самое, что и временная таблица, которую я предлагал ранее? Присоединяйтесь к этому и закажите desc. Он не будет работать (конечно, ничего не будет, когда структура плохо спроектирована), но он может справиться с этой задачей, если у вас нет миллионов записей.

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

0 голосов
/ 16 апреля 2009

спасибо за ваши ответы

слова разделяются пробелами, запятыми и / или точками с запятой, все разделители должны оставаться на месте

например. запись

'word1, word2 ;;; word3,'

оценивается в

'word3, word2 ;;; word1,'

в соответствии с требованиями существующей системы это необходимо сделать используя один запрос,

я пробовал:

update t_desc set name = 
(select name
from
(select name,
case when wb is null then rname when wb >= we then stuff(rname, wb, 128, REVERSE        (substring(rname, wb, 128))) else
stuff(rname, wb, we-wb+1, REVERSE(substring(rname, wb, we-wb+1))) end rname,
case when wb is null or wb > we then null else PATINDEX('%[a-z0-9]%', SUBSTRING(rname, we+1, 128))+we end wb,
case when we is null or wb > we then null else PATINDEX('%[a-z0-9][^a-z0-9]%', SUBSTRING(rname, we+1, 128))+we end we
from
(select name,
case when wb is null then rname when wb >= we then stuff(rname, wb, 128, REVERSE    (substring(rname, wb, 128))) else
stuff(rname, wb, we-wb+1, REVERSE(substring(rname, wb, we-wb+1))) end rname,
case when wb is null or wb > we then null else PATINDEX('%[a-z0-9]%', SUBSTRING    (rname, we+1, 128))+we end wb,
case when we is null or wb > we then null else PATINDEX('%[a-z0-9][^a-z0-9]%',     SUBSTRING(rname, we+1, 128))+we end we
from
(select name,
case when wb is null then rname when wb >= we then stuff(rname, wb, 128, REVERSE        (substring(rname, wb, 128))) else
stuff(rname, wb, we-wb+1, REVERSE(substring(rname, wb, we-wb+1))) end rname,
case when wb is null or wb > we then null else PATINDEX('%[a-z0-9]%', SUBSTRING        (rname, we+1, 128))+we end wb,
case when we is null or wb > we then null else PATINDEX('%[a-z0-9][^a-z0-9]%',         SUBSTRING(rname, we+1, 128))+we end we
from
(select name, 
stuff(rname, wb, we-wb+1, REVERSE(substring(rname, wb, we-wb+1))) rname,
PATINDEX('%[a-z0-9]%', SUBSTRING(rname, we+1, 128))+we wb,
PATINDEX('%[a-z0-9][^a-z0-9]%', SUBSTRING(rname, we+1, 128))+we we 
from
(select name, rname, 
PATINDEX('%[a-z0-9]%', rname) wb,
PATINDEX('%[a-z0-9][^a-z0-9]%', rname) we
  from
(select t_desc.name, REVERSE(name) rname) t1) t2) t3) t4) t5) t6)

и подобные идеи, но это не сработало

редактирование: все, кроме букв и цифр, являются разделителями

edit2: к сожалению, я не могу вызвать операторы ddl и не имею прямого доступа к базе данных, моя компания использует старое, закрытое программное обеспечение - мы можем использовать только консоль внешнего приложения для выбора или иногда обновления. я могу добавить свое обновление в список вакансий - оно будет выполняться каждый день в будущем.

таблица имеет около 60 тыс. Строк, столбец содержит от 2 до 20 слов, а не ноль

извините за мой английский :) 1026 *

0 голосов
/ 16 апреля 2009

Я думаю, вы могли бы создать новую таблицу и вставить в нее данные из первой таблицы.

ВСТАВИТЬ В ТАБЛИЦУ 2 ВЫБРАТЬ * ИЗ ТАБЛИЦЫ 1 ПОРЯДОК КОЛОННЫ 1 DESC

Затем удалите table2 и переименуйте table1.

Может быть ...

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