【问题标题】:Creating SELECT Statement to Filter Names from a Single Column创建 SELECT 语句以从单个列中过滤名称
【发布时间】:2019-04-18 00:23:34
【问题描述】:

我们有一列名称,需要解析多个内容,因为它必须以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

非常感谢任何帮助!

【问题讨论】:

  • 您可以使用 dbfiddle.uk 或 sqlfiddle.com 创建演示模式和数据吗?什么版本的 SQL?
  • 你将如何处理可以包含空格的名字?
  • 名字总是一团糟,但是有很多功能,例如ParseNameThis Solution look promising too@res74

标签: sql sql-server tsql


【解决方案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

如果没有 Middlename ,CTE 将处理它,但 select 需要更新为以下内容:-

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

【讨论】:

  • 非常感谢阿里。这是肯定的,但在我的信息中,我没有提到有时没有 MIDDLENAME。这完全是我的愚蠢,我为此道歉。您的 SELECT 是否也可以考虑到这一点?
  • 它非常接近,但如果 MIDDLENAME 在括号中,我只需要忽略它,因为我们不想在括号中显示任何内容。我还注意到,如果有 2 个 MIDDLENAME,它只需要最后一个。如果有 2 个,我可以要求您更新它以显示中间名吗?示例:ABDEL WAHAB,HODA GALAL HASSAN
  • 第一个选择管理那个,检查一下,以;开头的那个,FindBrackts as .....,如果有括号,它会删除中间名,即使有括号也会显示中间名它不止一个部分。
  • 感谢阿里!像魅力一样工作!
【解决方案2】:

请试试这个:

;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
;

感谢 Ali Al-Mosawi 提供的内存表示例

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-11-15
    • 2019-12-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-06
    • 2017-04-29
    相关资源
    最近更新 更多