TSql LIKE搜索逗号分隔数据

时间:2013-05-24 23:04:22

标签: sql sql-server sql-like

关于LIKE搜索的快速提问。如果我有一个值为'Analyst,Trainer'的列和另一列'Workflow,Analyst,Tester,Trainer',我想检查第一列中的值是否在第二列中。我们可以很容易地看出答案是肯定的,但它们不是有序的,所以我们不能做一个比较。

任何想法如何解决这个问题?可能会编写一个传递两个值的函数,并在两个函数上执行拆分例程?似乎可能有一种更简单的方法。

感谢您的耳朵。

大卫

3 个答案:

答案 0 :(得分:1)

虽然这可能更适合编写脚本,但尝试使用SQL很有意思。

首先,您需要一个行标识符 - 这使用ROW_NUMBER()。接下来,您可以查看使用CROSS APPLY拆分逗号分隔列表。然后,您可以相应地比较列表。

这是一个有效的例子:

WITH YOURTABLE_WITH_RN AS (
  SELECT ROW_NUMBER() OVER (ORDER BY col1) rn, 
    col1, 
    col2
  FROM YourTable
  ),
YOURTABLE_COL1 AS (
  SELECT rn,
    Split.a.value('.', 'VARCHAR(100)') AS col1 
  FROM  
  (
     SELECT ROW_NUMBER() OVER (ORDER BY col1) rn,
       CAST ('<M>' + REPLACE(col1, ',', '</M><M>') + '</M>' AS XML) AS col1
     FROM  YourTable
  ) AS A 
  CROSS APPLY col1.nodes ('/M') AS Split(a)
  ), 
YOURTABLE_COL2 AS (
  SELECT rn,
    Split.a.value('.', 'VARCHAR(100)') AS col2 
  FROM  
  (
     SELECT ROW_NUMBER() OVER (ORDER BY col1) rn,
       CAST ('<M>' + REPLACE(col2, ',', '</M><M>') + '</M>' AS XML) AS col2
     FROM  YourTable
  ) AS A 
  CROSS APPLY col2.nodes ('/M') AS Split(a)
  ) 
SELECT T.rn, 
  T.col1, 
  T.col2, 
  CASE WHEN T2.rn IS NULL THEN 'Y' ELSE 'N' END AllIncluded
FROM YOURTABLE_WITH_RN T
   LEFT JOIN (
    SELECT T.rn
    FROM YOURTABLE_COL1 T
        LEFT JOIN YOURTABLE_COL2 T2 ON T.rn = T2.rn AND T.col1 = T2.col2
    WHERE T2.rn IS NULL
   ) T2 ON T.rn = T2.rn

SQL Fiddle Demo

如果您的表中已有唯一标识符,则不需要第一个CTE(公用表表达式)或使用ROW_NUMBER()

答案 1 :(得分:0)

是的,我确实以这种方式冒险,然后在处理庞大的数据集时考虑了性能。我实际上前一段时间做了一些国际象棋编程,并认为可能会将这些值转换为'Analyst,Tester,Trainer',将ya转换为相应表中的位值,这样您在此处看到的值可能是7(1,2,4)然后也许'分析师,培训师'可能是5(1,4)所以如果我想测试'分析员,培训师'是否在'分析员,测试员,培训师'中我可以测试(7&amp; 5)= 5。好像它会起作用。这就是我们如何测试棋子是否在攻击广场上的方法。不知道为什么我之前没有发生这种情况。感谢您的评论。

答案 2 :(得分:0)

您可以使用XQuery方法(节点,值)拆分包含“Analyst,Trainer”值的列,然后使用LIKE运算符与“Workflow,Analyst,Tester,Trainer”值进行比较。

SELECT t.col1, t.col2, MIN(CASE WHEN t.col2 LIKE '%' + o.col1 + '%'
                                THEN 1 ELSE 0 END) AS IsMatch
FROM YourTable t 
  CROSS APPLY 
    (
     SELECT Split.a.value('.', 'nvarchar(100)')
     FROM (       
           SELECT CAST('<M>'+REPLACE(t.col1,',','</M><M>')+'</M>' AS xml) AS col1
           ) AS a
     CROSS APPLY col1.nodes('/M') AS Split(a)
     ) o(col1)
GROUP BY t.col1, t.col2

SQLFiddle上的演示

您还可以使用带动态管理功能的选项sys.dm_fts_parser 在脚本执行之前,您需要检查是否已安装全文组件:

SELECT FULLTEXTSERVICEPROPERTY ('IsFulltextInstalled')

0 =未安装全文。 1 =已安装全文。 NULL =输入无效或错误。

如果0 =未安装全文,则此帖子对您How to install fulltext on sql server 2008?

是必要的
SELECT t.col1, t.col2, MIN(CASE WHEN t.col2 LIKE '%' + o.col1 + '%'
                                THEN 1 ELSE 0 END) AS IsMatch
FROM YourTable t 
  CROSS APPLY (
               SELECT display_term
               FROM sys.dm_fts_parser('"'+ 'nn,' + t.col1 + '"', 1033, NULL, 0)  
               WHERE display_term NOT LIKE 'nn%'
               ) o(col1)
GROUP BY t.col1, t.col2

为避免排序操作,请使用index:

CREATE INDEX x ON YourTable(col1, col2)

仅供参考,最佳性能将来自sys.dm_fts_parser