我希望根据以下示例表,对以下内容有个快速的建议:
|Column1 |Column2 |Column3 |Column4 |
|--------|--------|--------|--------|
|ABC XYZ |DFG KIL |YUI XYZ |ABC IOH |
|YDT NJK |ABC HJK |NJM XYZ |WEC OPP |
我当时想能够建立一个查询来搜索同一列或不同列中的多个单词,以显示那些关键字和相关列。这,不用依靠游标。
即如果用户搜索关键字'ABC', 'YUI', 'OPP'
,我希望得到以下输出:
|Col1 |Col2 |Col3 |Col4 |Found Keyword|Keyword Found in |
|--------|--------|--------|--------|-------------|-----------------|
|ABC XYZ |DFG KIL |YUI XYZ |ABC IOH |ABC, YUI |Col1,Col3,Col4 |
|YDT NJK |ABC HJK |NJM XYZ |WEC OPP |ABC, OPP |Col2,Col4 |
我一直在尝试做(sys.columns, UNION ALL, CROSS JOIN)
之类的各种事情,但到目前为止收效甚微。
行数超过10万,什么是最好的方法?
注意:我正在使用SQL Server 2012版本。
答案 0 :(得分:0)
糟糕!这是一种可怕的数据格式。您不应在列中存储多个值。但是您可以使用巨型case
表达式。例如,对于“找到的关键字”结果:
select t.*,
stuff( (case when col1 like '%' + @word1 + '%' or col1 like '%' + @word2 + '%' or col1 like '%' + @word3'
then ',col1' else ''
end) +
(case when col2 like '%' + @word1 + '%' or col2 like '%' + @word2 + '%' or col2 like '%' + @word3'
then ',col2' else ''
end) +
(case when col3 like '%' + @word1 + '%' or col3 like '%' + @word2 + '%' or col3 like '%' + @word3'
then ',col3' else ''
end), 1, 1, '') as keyword_found_in
from t;
您可以将类似的逻辑应用于找到的关键字。如果需要,您可以调整逻辑以考虑定界符。
答案 1 :(得分:0)
已经有人评论您的设计应该重新设计。
现在,这是一个应该响应您的用例的查询。通过在子查询中声明要搜索的词(这样就很容易添加更多的词),然后声明JOIN
与表:基本上,检查所有串联的列是否与搜索到的列匹配就足够了值(假设使用空格分隔符)。
然后,外部查询使用STRING_AGG()
(在SQL Server 2017中可用)执行聚合作业。生成与之匹配的列列表的部分有些棘手,因为需要为每条记录手动生成CSV值。
NB:如果您有一个唯一的列(或列的组合),可以避免在汇总时混合记录,这将是很好的选择。我假设一个名为id
的主键列。
查询:
SELECT
t.Col1,
t.Col2,
t.Col3,
t.Col4,
STRING_AGG(words.txt, ',') FoundKeywords,
STRING_AGG(
STUFF(CONCAT(
IIF(CONCAT(' ', t.Col1, ' ') LIKE CONCAT(' %', words.txt, '% '), ',Col1', ''),
IIF(CONCAT(' ', t.Col2, ' ') LIKE CONCAT(' %', words.txt, '% '), ',Col2', ''),
IIF(CONCAT(' ', t.Col3, ' ') LIKE CONCAT(' %', words.txt, '% '), ',Col3', ''),
IIF(CONCAT(' ', t.Col4, ' ') LIKE CONCAT(' %', words.txt, '% '), ',Col4', '')
), 1, 1, ''),
','
) KeywordFoundin
FROM
mytable t
INNER JOIN (
SELECT 'ABC' txt UNION ALL SELECT 'YUI' UNION ALL SELECT 'OOP'
) words
ON CONCAT(' ', t.Col1, ' ', t.Col2, ' ', t.Col3, ' ', t.col4, ' ')
LIKE CONCAT(' %', words.txt, '% ')
GROUP BY
t.id,
t.Col1,
t.Col2,
t.Col3,
t.Col4
Col1 | Col2 | Col3 | Col4 | FoundKeywords | KeywordFoundin :------ | :------ | :------ | :------ | :------------ | :------------- ABC XYZ | DFG KIL | YUI XYZ | ABC IOH | ABC,YUI | Col1,Col4,Col3 YDT NJK | ABC HJK | NJM XYZ | WEC OPP | ABC | Col2
在无法使用STRING_AGG()
的SQL Server <2017中,我将使用一个带有很长表达式的简单SELECT
来比较和连接所需的信息:
SELECT
Col1,
Col2,
Col3,
Col4,
STUFF(CONCAT(
IIF(CONCAT(' ', Col1, ' ', Col2, ' ', Col3, ' ', Col4, ' ') LIKE CONCAT(' %', 'ABC', '% '), ',ABC', ''),
IIF(CONCAT(' ', Col1, ' ', Col2, ' ', Col3, ' ', Col4, ' ') LIKE CONCAT(' %', 'YUI', '% '), ',YUI', ''),
IIF(CONCAT(' ', Col1, ' ', Col2, ' ', Col3, ' ', Col4, ' ') LIKE CONCAT(' %', 'OOP', '% '), ',OOP', '')
), 1, 1, '') FoundKeywords,
STUFF(CONCAT(
IIF(
CONCAT(' ', Col1, ' ') LIKE CONCAT(' %', 'ABC', '% ')
OR CONCAT(' ', Col1, ' ') LIKE CONCAT(' %', 'YUI', '% ')
OR CONCAT(' ', Col1, ' ') LIKE CONCAT(' %', 'OOP', '% '),
',Col1',
''
),
IIF(
CONCAT(' ', Col2, ' ') LIKE CONCAT(' %', 'ABC', '% ')
OR CONCAT(' ', Col2, ' ') LIKE CONCAT(' %', 'YUI', '% ')
OR CONCAT(' ', Col2, ' ') LIKE CONCAT(' %', 'OOP', '% '),
',Col2',
''
),
IIF(
CONCAT(' ', Col3, ' ') LIKE CONCAT(' %', 'ABC', '% ')
OR CONCAT(' ', Col3, ' ') LIKE CONCAT(' %', 'YUI', '% ')
OR CONCAT(' ', Col3, ' ') LIKE CONCAT(' %', 'OOP', '% '),
',Col3',
''
),
IIF(
CONCAT(' ', Col4, ' ') LIKE CONCAT(' %', 'ABC', '% ')
OR CONCAT(' ', Col4, ' ') LIKE CONCAT(' %', 'YUI', '% ')
OR CONCAT(' ', Col4, ' ') LIKE CONCAT(' %', 'OOP', '% '),
',Col4',
''
)
), 1, 1, '') KeywordFoundin
FROM mytable
WHERE
CONCAT(' ', Col1, ' ', Col2, ' ', Col3, ' ', col4, ' ') LIKE CONCAT(' %', 'ABC', '% ')
OR CONCAT(' ', Col1, ' ', Col2, ' ', Col3, ' ', col4, ' ') LIKE CONCAT(' %', 'YUI', '% ')
OR CONCAT(' ', Col1, ' ', Col2, ' ', Col3, ' ', col4, ' ') LIKE CONCAT(' %', 'OOP', '% ')