1

关于 LIKE 搜索的快速问题。如果我有一列的值为“Analyst,Trainer”和另一列“Workflow,Analyst,Tester,Trainer”,我想检查第一列中的值是否在第二列中。我们可以很容易地看到答案是肯定的,但它们不是按顺序排列的,所以我们不能只做类似的比较。

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

谢谢你的耳朵。

大卫

4

3 回答 3

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 小提琴演示

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

于 2013-05-24T23:50:05.887 回答
0

是的,我确实以这种方式冒险了一下,然后考虑了处理庞大数据集时的性能。实际上,我不久前做了一些国际象棋编程,并认为可能将这些值(如“分析员、测试员、培训师”)转换为相应表中的位值,因此您在此处看到的值可能是 7 (1,2,4)然后也许'Analyst,Trainer'可能是5(1,4)所以如果我想测试'Analyst,Trainer'是否在'Analyst,Tester,Trainer'内,我可以测试(7&5)= 5。这似乎就像它会工作一样。这就是我们可以测试棋子是否在攻击方格上的方法。不知道为什么我之前没有想到这一点。不过感谢您的评论。

于 2013-05-25T00:52:44.350 回答
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 = 全文未安装,那么这篇文章对您来说是必要的如何在 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

为了避免排序操作,使用索引:

CREATE INDEX x ON YourTable(col1, col2)

仅供参考,最好的性能将是 sys.dm_fts_parser

于 2013-05-25T06:50:57.790 回答