【问题标题】:Complex string match in SQL QuerySQL 查询中的复杂字符串匹配
【发布时间】:2011-10-06 19:56:48
【问题描述】:

我有一个复杂的字符串匹配场景,希望得到你们的输入。 我有一个名为客户的表。此表包含一个字段 CustomerName varchar。 列中的数据以 Mr. Mrs. Ms. 为前缀。 数据可能是

  1. 先生约翰·布雷迪
  2. 女士亚伯拉罕列宁
  3. 夫人约翰·布雷迪
  4. 先生迈克尔·金
  5. 夫人尼尔·托马斯
  6. 夫人迈克尔·金

现在我需要设计一个搜索查询,它以有序的方式返回只有 Couples 的行。

喜欢 Select CustomerName from Customer where ...?? 结果需要像

  1. 先生约翰·布雷迪
  2. 夫人约翰·布雷迪
  3. 先生迈克尔·金
  4. 夫人迈克尔·金

有什么想法吗?

提前感谢您的考虑。

【问题讨论】:

  • 到目前为止,您尝试过哪些 SQL 查询?
  • 到目前为止还没有一个查询。虽然可以使用 SP 完成多个查询和字符串解析,但这对于大量数据集来说太昂贵了。

标签: sql sql-server string sql-server-2008 tuples


【解决方案1】:
declare @T table(Name varchar(25))

insert into @T values
    ('Mr. John Brady'),
    ('Ms. Abraham Lenin'),
    ('Mrs. John Brady'),
    ('Mr. Michael King'),
    ('Mrs. Neil Thomas'),
    ('Mrs. Michael King')

;with C as
(
  select Name, 
         count(*) over(partition by stuff(Name, 1, charindex(' ', Name), '')) as Cnt
  from @T
)    
select Name
from C
where Cnt = 2

【讨论】:

  • 感谢 Randy 和 Mikael,你们都提出了一个很好的解决方案,也让我在编写查询方面更进一步。查看 Mikael 提出的解决方案非常简洁,更适合我的场景。所以我继续前进并将其标记为答案。感谢两位大师帮助我解决这个问题。
【解决方案2】:

如果您真的信任您的数据,解决方案如下:

--proof of concept preparation start

declare @YourTable table (name varchar(50))

insert into @YourTable (name) values
('Mr. John Brady'),
('Ms. Abraham Lenin'),
('Mrs. John Brady'),
('Mr. Michael King'),
('Mrs. Neil Thomas'),
('Mrs. Michael King')

--proof of concept preparation end

;with purenames as (
    select name, 
           LEFT(name, CHARINDEX(' ', name, 0)) salutation,
           RIGHT(name, LEN(name) - CHARINDEX(' ', name, 0)) purename
    from @YourTable
)

select p1.name
from purenames p1
inner join purenames p2 
on p1.purename = p2.purename and p1.salutation <> p2.salutation
order by p1.purename, p1.name

但是,只有当姓名的第一个单词始终是称呼时,这才能完美运行(请记住,您必须信任您的数据)。

当然,我必须将Mrs. Micheal King 修复为Mrs. Michael King,因此纯名称(无称呼)必须相同。

我是否提到过有关信任您的数据的内容?好吧,坏消息是,根据经验,你不能相信数据。但是,如果您有良好的数据,您应该能够识别出大量的夫妻。

【讨论】:

  • +1 表示对信任数据的多次引用,例如。不要相信它!
【解决方案3】:

我怀疑这是一个现实生活中的解决方案......但你首先需要规范你的字符串。 (在传统的 RDBMS 意义上,和/或在字符串意义上)

我不太确定您的真实数据是否如此干净,但您可以查找第一个 '. ' 字符序列,使用剩余的子字符串,然后根据它检查是否相等。

对排序规则的原始字符串使用 order by。

【讨论】:

  • 这就是我最终要做的,但只有在我知道没有更好的方法来实现它之后。
【解决方案4】:
  WITH pattern_cnt 
     AS (SELECT string_pattern, 
                Count(string_pattern) AS CNT 
         FROM   (SELECT Substr(NAME, Instr(NAME, '.') + 1) AS STRING_PATTERN 
                 FROM   couples) 
         GROUP  BY string_pattern), 
     string_match 
     AS (SELECT NAME, 
                Substr(NAME, Instr(NAME, '.') + 1) AS PATTERN 
         FROM   couples) 
SELECT a.NAME 
FROM   pattern_cnt b, 
       string_match a 
WHERE  a.pattern = b.string_pattern 
       AND b.cnt > 1; 

【讨论】:

    猜你喜欢
    • 2014-06-19
    • 2014-07-21
    • 2017-12-25
    • 1970-01-01
    • 1970-01-01
    • 2021-09-29
    • 1970-01-01
    • 2022-08-11
    • 2011-04-09
    相关资源
    最近更新 更多