关于 LIKE 搜索的快速问题。如果我有一列的值为“Analyst,Trainer”和另一列“Workflow,Analyst,Tester,Trainer”,我想检查第一列中的值是否在第二列中。我们可以很容易地看到答案是肯定的,但它们不是按顺序排列的,所以我们不能只做类似的比较。
任何想法如何解决这个问题?可能编写一个函数来传递两个值并在两者上执行拆分例程?似乎可能有更简单的方法。
谢谢你的耳朵。
大卫
关于 LIKE 搜索的快速问题。如果我有一列的值为“Analyst,Trainer”和另一列“Workflow,Analyst,Tester,Trainer”,我想检查第一列中的值是否在第二列中。我们可以很容易地看到答案是肯定的,但它们不是按顺序排列的,所以我们不能只做类似的比较。
任何想法如何解决这个问题?可能编写一个函数来传递两个值并在两者上执行拆分例程?似乎可能有更简单的方法。
谢谢你的耳朵。
大卫
虽然这可能更适合使用脚本编写,但尝试使用 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
ROW_NUMBER()
如果您的表中已有唯一标识符,则 不需要第一个 CTE(通用表表达式)或使用。
是的,我确实以这种方式冒险了一下,然后考虑了处理庞大数据集时的性能。实际上,我不久前做了一些国际象棋编程,并认为可能将这些值(如“分析员、测试员、培训师”)转换为相应表中的位值,因此您在此处看到的值可能是 7 (1,2,4)然后也许'Analyst,Trainer'可能是5(1,4)所以如果我想测试'Analyst,Trainer'是否在'Analyst,Tester,Trainer'内,我可以测试(7&5)= 5。这似乎就像它会工作一样。这就是我们可以测试棋子是否在攻击方格上的方法。不知道为什么我之前没有想到这一点。不过感谢您的评论。
您可以使用 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