SQL适当案例函数查询细化

Posted

技术标签:

【中文标题】SQL适当案例函数查询细化【英文标题】:SQL Proper Case Function Query Refinement 【发布时间】:2014-05-20 08:34:09 【问题描述】:

我有一个名称表,我正在尝试将其从大写转换为正确大小写。下面的代码几乎完全符合我的要求。当我测试它时,我注意到有些人的名字中有罗马数字,Mc* 和 O'* 在表中。自然地,该查询将任何多个罗马数字转换为 Iv,就像它应该做的那样,任何 MCDONALDS 或 O'DANIEL 都被转换为 Mcdonalds 和 O'daniel。我试图弄清楚如何对这个函数进行彻底的更改,以便我可以运行我的更新查询,但我仍然在下班时间将我的 SQL 知识和平磨合在一起。任何帮助/建议将不胜感激。我进行了谷歌搜索并找到了几个示例,但我尝试过的那些都不起作用。我必须做的更正量相对较小(1000 行表中的 17 次更正),但我想尝试整理它以尽可能减少人为错误。

提前感谢您的帮助。

CREATE FUNCTION [dbo].[f_ProperCase]
(@Text as varchar(80))
RETURNS varchar(80) as
BEGIN

DECLARE @Reset bit
DECLARE @Ret varchar(80)
DECLARE @i int
DECLARE @c char(1)

SELECT @Reset = 1, @i=1, @Ret = ''

WHILE @i <= LEN(@Text)
SELECT @c= SUBSTRING(@Text,@i,1),
@Ret = @Ret + CASE WHEN @Reset=1 THEN UPPER(@c) ELSE LOWER(@c) END,
@Reset= CASE WHEN 
CASE WHEN SUBSTRING(@Text,@i-4,5) like '_[a-z] [DOL]''' THEN 1 
WHEN SUBSTRING(@Text,@i-4,5) like '_[a-z] [D][I]' THEN 1 
WHEN SUBSTRING(@Text,@i-4,5) like '_[a-z] [M][C]' THEN 1 
WHEN SUBSTRING(@Text,@i-4,5) like '_[a-z] [M][c][*]' THEN 1 --Convert MCDONALD to     McDonald
WHEN SUBSTRING(@Text,@I-4,5) like '_[a-z] [O][''][*]' THEN 1 --Convert O'DONNEL to O'Donnel
ELSE 0 
END = 1 
THEN 1 
ELSE CASE WHEN @c like '[a-zA-Z]' or @c in ('''') THEN 0 
ELSE 1 
END 
END,
@i = @i +1
RETURN @Ret
end

【问题讨论】:

【参考方案1】:

我调整了一些以处理名称中包含的后缀。这几乎处理了我扔给它的任何东西。我们有时在一些后缀之后有连字符的名称和句点。我知道从 I-IX 处理是多余的,但很容易将 X 添加到 V 检查。

ALTER FUNCTION dbo.udf_ProperCase
(@Text as varchar(1024))
RETURNS varchar(1024) 
AS
/* 
Created to ProperCase most common LastName (Mc/Mac/O'/D'/L') and handle I(first)-IX(nineteenth) suffixes

Original Code: https://***.com/questions/22923616/sql-proper-case-function-query-refinement
SELECT dbo.udf_ProperCase('iitest demetrii mcdonald o''neil victor second 2nd ii iii iv v vi vii viii ix x xi test')
*/
BEGIN
    DECLARE @Reset bit
    DECLARE @Ret varchar(1024)
    DECLARE @i int
    DECLARE @c char(1)
    DECLARE @Text1 varchar(1025)

    SELECT @Reset = 1, @i=1, @Ret = '', @Text1 = ' ' + @Text + '  '  --Ensure one space before to make first char upper and after to handle suffixes
    --Loop through each character, comparing prior/next to determine if need to handle
    WHILE @i <= LEN(@Text1)
      BEGIN
        SELECT 
             @c= SUBSTRING(@Text1,@i,1)
            ,@Ret = @Ret + CASE WHEN @Reset=1 THEN UPPER(@c) ELSE LOWER(@c) END
            ,@Reset= CASE 
                        WHEN 
                            CASE 
                                WHEN SUBSTRING(@Text1,@i-2,3) like '[ -][DdOoLl][''`]' THEN 1   --Names (including hyphenated) beginning with D/O/L                             
                                WHEN SUBSTRING(@Text1,@i-2,4) like ' [Mm][cC][a-zA-Z]' THEN 1  --Names with Mc
                                WHEN SUBSTRING(@Text1,@i-3,5) like ' [Mm][Aa][cC][a-zA-Z]' THEN 1  --Names with Mac
                                WHEN SUBSTRING(@Text1,@i-1,4) like ' [Ii][Ii][ .]' THEN 1  --Handle II (include ending with Space or period)
                                WHEN SUBSTRING(@Text1,@i-1,5) like ' [Ii][Ii][Ii][ .]' THEN 1  --Handle III
                                WHEN SUBSTRING(@Text1,@i-2,4) like ' [Ii][Ii][ .]' THEN 1  --Handle II
                                WHEN SUBSTRING(@Text1,@i-2,5) like ' [Ii][Ii][Ii][ .]' THEN 1  --Handle III
                                WHEN SUBSTRING(@Text1,@i-3,4) like ' [Ii][Ii][ .]' THEN 1  --Handle II
                                WHEN SUBSTRING(@Text1,@i-3,5) like ' [Ii][Ii][Ii][ .]' THEN 1  --Handle III
                                
                                WHEN SUBSTRING(@Text1,@i-1,4) like ' [Ii][VvXx][ .]' THEN 1 --Handle IV

                                WHEN SUBSTRING(@Text1,@i-1,4) like ' [VvXx][Ii][ .]' THEN 1  --Handle VI
                                WHEN SUBSTRING(@Text1,@i-1,5) like ' [VvXx][Ii][Ii][ .]' THEN 1  --Handle VII
                                WHEN SUBSTRING(@Text1,@i-1,6) like ' [VvXx][Ii][Ii][Ii][ .]' THEN 1  --Handle VIII
                                WHEN SUBSTRING(@Text1,@i-2,4) like ' [VvXx][Ii][ .]' THEN 1  --Handle VI
                                WHEN SUBSTRING(@Text1,@i-2,5) like ' [VvXx][Ii][Ii][ .]' THEN 1  --Handle VII
                                WHEN SUBSTRING(@Text1,@i-2,6) like ' [VvXx][Ii][Ii][Ii][ .]' THEN 1  --Handle VIII
                                WHEN SUBSTRING(@Text1,@i-3,4) like ' [VvXx][Ii][ .]' THEN 1  --Handle VI
                                WHEN SUBSTRING(@Text1,@i-3,5) like ' [VvXx][Ii][Ii][ .]' THEN 1  --Handle VII
                                WHEN SUBSTRING(@Text1,@i-3,6) like ' [VvXx][Ii][Ii][Ii][ .]' THEN 1  --Handle VIII
                                ELSE 0 
                            END = 1 THEN 1 
                        ELSE 
                            CASE 
                                WHEN @c like '[a-zA-Z`]' or @c in ('''') or @c like '[0-9]' THEN 0  --If any letter, single-quote or number, then keep next lowercase
                                ELSE 1  --Anything else (e.g. Space dash, And(&), etc. make next Upper-Case)
                            END 
                      END
            ,@i = @i +1 
      END   
    
    RETURN stuff(@Ret, 1, 1, '')
END

GO

【讨论】:

【参考方案2】:

我会做不同的事情:

CREATE FUNCTION [dbo].[f_ProperCase]
(@Text as varchar(80))
RETURNS varchar(80) as
BEGIN

DECLARE @Reset bit
DECLARE @Ret varchar(80)
DECLARE @i int
DECLARE @c char(1)
DECLARE @Text1 varchar(81)

SELECT @Reset = 1, @i=1, @Ret = '', @Text1 = ' ' + @Text

WHILE @i <= LEN(@Text1)
    SELECT @c= SUBSTRING(@Text1,@i,1),
    @Ret = @Ret + CASE WHEN @Reset=1 THEN UPPER(@c) ELSE LOWER(@c) END,
    @Reset= CASE WHEN 
    CASE WHEN SUBSTRING(@Text1,@i-2,3) like ' [DdOoLl]''' THEN 1 
    WHEN SUBSTRING(@Text1,@i-2,4) like ' [Mm][cC][a-zA-Z]' THEN 1 
    WHEN SUBSTRING(@Text1,@i-3,5) like ' [Mm][Aa][cC][a-zA-Z]' THEN 1 
    ELSE 0 
    END = 1 
    THEN 1 
    ELSE CASE WHEN @c like '[a-zA-Z]' or @c in ('''') THEN 0 
    ELSE 1 
    END 
    END,
    @i = @i +1
RETURN stuff(@Ret, 1, 1, '')
end

此功能支持O'、L'、D',以及Mc、Mac。该函数还可以从任何大小写(不仅是大写)转换为正确的大小写

SQL Fiddle

select dbo.f_ProperCase('CORMACK')
      ,dbo.f_ProperCase('Mcdonald ronald')
      ,dbo.f_ProperCase('o''hara')

|         |                 |        |
|---------|-----------------|--------|
| Cormack | McDonald Ronald | O'Hara |

【讨论】:

我只是在我的测试系统中厌倦了这个,它就像一个魅力。非常感谢你的帮助,Cha。 效果很好,唯一的问题是对于像“CORMACK”这样的名称,它将返回“CormacK” 太棒了,感谢您花时间更新,完美运行 有人在 mysql 中有这个工作吗?我的函数语法很弱,似乎无法让它工作。

以上是关于SQL适当案例函数查询细化的主要内容,如果未能解决你的问题,请参考以下文章

LINQ 左外连接查询错误:OuterApply 没有适当的键

Mysql基础编写sql案例

2021年大数据ELK(十六):Elasticsearch SQL(职位查询案例)

MySQL进阶8 分页查询(limit) - SQL查询语法顺序及大致结构- 子查询的3个经典案例

NewRelic 在具有适当索引的表之一上报告的 SQL Server 2008 查询缓慢

SQL 分组使用案例