通过案例陈述SQL实现

时间:2016-10-18 06:21:54

标签: sql-server tsql case

我试图在SQL中执行一些数据清理。我有一个主数据表,其中包含每个不正确的条目的CASE语句,如

CASE when location LIKE '%gov%' THEN REPLACE <gov with govt>
     when location LIKE '%primery%' THEN REPLACE <primery with primary>

例如:我需要&#39; gov primery skool&#39;成为政府小学&#39;。大约有40个这样的单词需要使用正确的条目进行更新。因此,对这些单词的每一个组合进行操作都不会扩大规模。

我做了一些研究,发现SQL不允许在这种情况下有所帮助的案例陈述。关于如何实施这一点的任何想法?

3 个答案:

答案 0 :(得分:1)

我认为你在这里最好的选择是维护一个你想要在数据中找到和替换的拼写错误表。这可以使用静态引用表(推荐)完成,或者如果不能添加表,那么过程中的表变量就足够了。

使用此单个单词列表,您可以使用递归cte循环遍历数据,依次替换每个拼写错误并返回最终结果。使用这种方法,您只需按照建议的其他一些答案维护单个单词列表而不是整个句子。您需要将数据插入到临时表中,以便以相同的顺序保留row_numbercount,以防您有重复的行。

以下查询的输出:

TextValue             | NewTextValue
----------------------+----------------------
gov primery skool     | govt primary school
Not so incorect name  | Not so incorrect name
-- Create data to use.
declare @Data table (TextValue nvarchar(50));
declare @Lookup table (IncorrectValue nvarchar(50),CorrectValue nvarchar(50));

insert into @Data values
 ('gov primery skool')
,('Not so incorect name');

insert into @Lookup values
 ('gov','govt')
,('primery','primary')
,('skool','school')
,('incorect','incorrect');



-- Actual query.
if object_id('tempdb..#DataRN') is not null
drop table #DataRN;

create table #DataRN (rn int
                        ,cnt int
                        ,cntrn int
                        ,TextValue nvarchar(50)
                        ,IncorrectValue nvarchar(50)
                        ,CorrectValue nvarchar(50)
                        );

-- Create temp table that holds source data as well as some Row Numbers and Counts by TextValue to determine what order to retreive rows and to know which is the final row to pull out at the end.
insert into #DataRN
select row_number() over (order by d.TextValue, l.IncorrectValue, l.CorrectValue) as rn     -- Provides order to select rows in cte below.
    ,row_number() over (partition by d.TextValue
                        order by d.TextValue, l.IncorrectValue, l.CorrectValue) as cntrn    -- Provides ordering within each TextValue, to be compared with 
    ,count(*) over (partition by d.TextValue) as cnt                                        -- The total number of rows returned to complete all REPLACEs on the TextValue to find the last, and therefore complete, NewTextValue in cte.
    ,d.TextValue
    ,l.IncorrectValue
    ,l.CorrectValue
from @Data d
        left join @Lookup l
            on(d.TextValue like '%' + l.IncorrectValue + '%');


-- Recursive cte to apply each find and replace in order.
with cte as
(
    select d.rn
            ,d.cnt
            ,d.cntrn
            ,d.TextValue
            ,cast(replace(d.TextValue,d.IncorrectValue,d.CorrectValue) as nvarchar(50)) as NewTextValue
    from #DataRN d
    where rn = 1

    union all

    select d.rn
            ,d.cnt
            ,d.cntrn
            ,d.TextValue
            ,cast(replace(case when d.TextValue = c.TextValue
                                then c.NewTextValue
                                else d.TextValue
                                end
                            ,d.IncorrectValue
                            ,d.CorrectValue
                            ) as nvarchar(50)) as NewTextValue
    from #DataRN d
        inner join cte c
            on(d.rn = c.rn+1)
) 
select TextValue
        ,NewTextValue
from cte
where cnt = cntrn   -- Where these two values are the same, we know that is the finished product.
order by 1;




if object_id('tempdb..#DataRN') is not null
drop table #DataRN;

答案 1 :(得分:0)

您需要使用 CASE 子句更新语句。

UPDATE YourTabel  
SET     YourField=  CASE  
                        WHEN YourField= 'gov primery skool' THEN 'Government primary school' 
                        WHEN YourField= 'ABC' THEN 'XYZ'
                        ELSE YourField
                    END 

答案 2 :(得分:0)

您可以在案例陈述中使用 OR 条件。

    update TableName
    set Field = case when fieldname='gov primery skool' or fieldname='gov skool primery' then 'Government primary school'
    else fieldname end