如何反转列中的单词

时间:2009-04-15 18:54:33

标签: sql sql-server sql-server-2005 tsql

我有一个带varchar(128)列的表,其数据如下:

word1,word2,word3,word4
word1,word2,word3 ,,
word1 ,,,,; WORD2
; word1 word2,word3

我必须更新此表,使单词反向顺序:

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

你能帮助我只使用单个SQL查询吗?

5 个答案:

答案 0 :(得分:2)

要完成此任务,需要使用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 :(得分:1)

最好的办法是永远不要以这种方式存储数据。如果这是一个相关的表格,那么你可以订购你的内心。就个人而言,至少将数据拆分为具有额外标识列的temptable或表变量,然后按该列的desc顺序排序可能是最快的。

答案 2 :(得分:0)

我认为您可以创建一个新表并在该表中插入第一个表中的数据。

INSERT INTO TABLE2 SELECT * FROM TABLE1 ORDER BY COLUMN1 DESC

然后,删除table2并重命名table1。

也许......

答案 3 :(得分:0)

感谢您的回答

单词用空格,逗号和/或分号分隔, 所有分隔符都应该留在原地

e.g。记录

'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语句,我没有直接访问数据库, 我的公司使用旧的,封闭的软件 - 我们只能使用外部应用程序的控制台来选择或有时更新。 我可以将我的更新添加到作业列表 - 它将在未来每天执行。

表有大约60k行, 列包含2到20个单词,不为空

抱歉我的英语:)

答案 4 :(得分:0)

我有一个想法,因为你受限于一个查询。你能创建一个表值UDF,它会像我之前建议的临时表那样做吗?加入并订购desc。它不会是高效的(当然结构设计得不好时,什么都不会),但除非你有数百万条记录,否则它可能会起作用。

或者你可以制作一个存储过程,只需从你的GUI调用它,这将允许你有多个步骤。