创建SELECT语句以从单列中过滤名称

时间:2019-04-16 18:11:54

标签: sql sql-server tsql

我们有一列名称,由于要以LASTNAME FIRSTNAME MIDDLENAME的形式出现,因此需要解析多个内容。该列始终以LASTNAME开头,然后以逗号分隔为FIRSTNAME,然后对于(),可以将其用逗号分隔或空格分隔,甚至用括号分隔(MIDDLENAME)。

我有用于过滤LASTNAME的代码:

SUBSTRING([Name], 0, PATINDEX('%,%', [Name])) AS LastName

但是我无法通过FIRSTNAMEMIDDLENAME进行过滤。这是列的外观示例

LASTNAME,FIRSTNAME MIDDLENAME
LASTNAME,FIRSTNAME,MIDDLENAME
LAST NAME,FIRSTNAME MIDDLENAME
LAST NAME,FIRSTNAME (MIDDLENAME)

现在,如果括号中有内容,我们不想在括号中显示该信息。因此我们将忽略MIDDLENAME。该列可以包含LASTNAMEFIRSTNAMEMIDDLENAME的任意组合,并带有空格或逗号或方括号,并且MIDDLENAME也可以存在于方括号之外:

LASTNAME,FIRSTNAME (NICKNAME) MIDDLENAME

在这种情况下,我们希望MIDDLENAME并忽略NICKNAME

非常感谢您的帮助!

2 个答案:

答案 0 :(得分:1)

我会将您的示例添加到内存表中,以便我们可以对其进行如下测试:-(您不需要这样做)

Declare @NameTable table (fullname varchar(250))
insert into @NameTable values
('LASTNAME,FIRSTNAME MIDDLENAME'),
('LASTNAME,FIRSTNAME,MIDDLENAME'),
('LAST NAME,FIRSTNAME MIDDLENAME'),
('LAST NAME,FIRSTNAME (MIDDLENAME)'),
('LASTNAME,FIRSTNAME (NICKNAME) MIDDLENAME'),
('LASTNAME,FIRSTNAME') -- no middle name

让我们尝试将其分解为一些较小的步骤,首先将方括号括起来,然后再姓氏,然后继续直到我们掌握所有部分为止。

;with FindBrackts as (
/* get rid of brackets */
select *,CHARINDEX('(',fullname) bStart,CHARINDEX(')',fullname) bEnd from @NameTable
),RemoveBrackts as (
    select case when bStart>0 then substring(fullname,1,bStart-1)+substring(fullname,bEnd+2,len(fullname)-bEnd+1)
        else fullname end fullname from FindBrackts)
,LastNameAndTheRest as (
    select substring(fullname,1,CHARINDEX(',',fullname)-1) [LASTNAME]
,substring(fullname,CHARINDEX(',',fullname)+1,len(fullname)-CHARINDEX(',',fullname)) [TheRest] from RemoveBrackts
),LastFirstMiddle as (
    select [LASTNAME],[TheRest],CHARINDEX(',',replace([TheRest],' ',',')) [mStart] from LastNameAndTheRest
)
select [LASTNAME]
    ,case when mStart=0 then [TheRest] else substring([TheRest],1,[mStart]-1) end FIRSTNAME  
    ,case when mStart=0 then null else substring([TheRest],[mStart]+1,len([TheRest])-[mStart]) end MIDDLENAME 
    from LastFirstMiddle

结果将类似于以下内容:-

LASTNAME    FIRSTNAME   MIDDLENAME
========    =========   ==========
LASTNAME    FIRSTNAME   MIDDLENAME
LASTNAME    FIRSTNAME   MIDDLENAME
LAST NAME   FIRSTNAME   MIDDLENAME
LAST NAME   FIRSTNAME   NULL
LASTNAME    FIRSTNAME   MIDDLENAME

如果这有帮助,并且您发现还有更多条件,请添加它们,并可能会更新查询以考虑这些条件。

这与SQL Fiddle http://sqlfiddle.com/#!18/2dd42/2/0

相同

或者,如果您不需要任何CTE,它的时间可能会长一些,但是您可以尝试以下操作:-

select 
    SUBSTRING(fullname, 0, CHARINDEX(',', fullname)) AS LastName 
    ,SUBSTRING(replace(SUBSTRING(fullname,CHARINDEX(',', fullname)+1,len(fullname)-CHARINDEX(',', fullname)),' ',','),1,CHARINDEX(',',replace(SUBSTRING(fullname,CHARINDEX(',', fullname)+1,len(fullname)-CHARINDEX(',', fullname)),' ',','))-1) [FirstName]
    ,SUBSTRING(fullname,2+len(fullname)-CHARINDEX(',',reverse(replace(fullname,' ',','))),len(fullname)) MiddleName
    from @NameTable

结果如下所示(与以前的解决方案有些不同)

LastName    FirstName   MiddleName
========    =========   ==========
LASTNAME    FIRSTNAME   MIDDLENAME
LASTNAME    FIRSTNAME   MIDDLENAME
LAST NAME   FIRSTNAME   MIDDLENAME
LAST NAME   FIRSTNAME   (MIDDLENAME)
LASTNAME    FIRSTNAME   MIDDLENAME

如果没有中间名,则CTE将对其进行处理,但是需要将选择内容更新为以下内容:-

select 
    SUBSTRING(fullname, 0, CHARINDEX(',', fullname)) AS LastName 
    ,case when CHARINDEX(',',replace(SUBSTRING(fullname,CHARINDEX(',', fullname)+1,len(fullname)-CHARINDEX(',', fullname)),' ',','))>0 then
        SUBSTRING(replace(SUBSTRING(fullname,CHARINDEX(',', fullname)+1,len(fullname)-CHARINDEX(',', fullname)),' ',','),1,CHARINDEX(',',replace(SUBSTRING(fullname,CHARINDEX(',', fullname)+1,len(fullname)-CHARINDEX(',', fullname)),' ',','))-1) 
        else replace(SUBSTRING(fullname,CHARINDEX(',', fullname)+1,len(fullname)-CHARINDEX(',', fullname)),' ',',') end [FirstName]
    ,case when CHARINDEX(',',replace(SUBSTRING(fullname,CHARINDEX(',', fullname)+1,len(fullname)-CHARINDEX(',', fullname)),' ',','))>0 then
        SUBSTRING(fullname,2+len(fullname)-CHARINDEX(',',reverse(replace(fullname,' ',','))),len(fullname))
        else  NULL end MiddleName
    from @NameTable

这有点长,可能写得更短了。无论如何,结果将如下所示:-

LastName    FirstName   MiddleName
=========   =========   ==========
LASTNAME    FIRSTNAME   MIDDLENAME
LASTNAME    FIRSTNAME   MIDDLENAME
LAST NAME   FIRSTNAME   MIDDLENAME
LAST NAME   FIRSTNAME   (MIDDLENAME)
LASTNAME    FIRSTNAME   MIDDLENAME
LASTNAME    FIRSTNAME   NULL

答案 1 :(得分:0)

Please try this:

;WITH Data AS (
    SELECT a.ID,a.LastName
        ,REPLACE(REPLACE(REPLACE(REPLACE(a.RotN,' (','.'),')',''),',','.'),' ','.') AS [DotSplitName]
    FROM (
        SELECT ROW_NUMBER()OVER(ORDER BY (SELECT 1)) AS [ID]
            ,SUBSTRING(t.fullname,1,CHARINDEX(',',t.fullname)-1) AS [LastName]
            ,SUBSTRING(t.fullname,CHARINDEX(',',t.fullname)+1,999) AS [RotN] /*Rest of the name*/
        FROM @NameTable t
        WHERE t.fullname LIKE '%[,]%'
    ) a
)
SELECT d.ID,d.LastName
    ,COALESCE(PARSENAME(d.DotSplitName,3),PARSENAME(d.DotSplitName,2)) AS [FirstName]
    ,PARSENAME(d.DotSplitName,1) AS [MiddleName]
    ,CASE WHEN PARSENAME(d.DotSplitName,3) IS NOT NULL THEN PARSENAME(d.DotSplitName,2) ELSE NULL END AS [NickName]
FROM Data d
;

Thank you Ali Al-Mosawi for Memory table example