SQL seleccione onde o campo contém palavras
Preciso de uma selecção que devolva resultados como este:
SELECT * FROM MyTable WHERE Column1 CONTAINS 'word1 word2 word3'
e eu preciso de todos os resultados, isto é, isto inclui cadeias de caracteres com 'word2 word3 word1' ou 'word1 word3 word2' ou qualquer outra combinação dos três.
todas as palavras têm de estar no resultado.
14 answers
Bastante lento, mas Método de trabalho para incluir qualquer {[5] } de palavras:
SELECT * FROM mytable
WHERE column1 LIKE '%word1%'
OR column1 LIKE '%word2%'
OR column1 LIKE '%word3%'
Se precisar de todas as palavras para estar presente, use isto:
SELECT * FROM mytable
WHERE column1 LIKE '%word1%'
AND column1 LIKE '%word2%'
AND column1 LIKE '%word3%'
Se você quer algo mais rápido, você precisa olhar em busca de texto completo, e isso é muito específico para cada tipo de banco de dados.
Lembre-se que, se usar LIKE
para determinar se uma cadeia de caracteres é uma sub-sequência de outra cadeia de caracteres, terá de escapar aos caracteres correspondentes aos padrões no seu texto de pesquisa.
Se o seu dialecto SQL suporta CHARINDEX
, é muito mais fácil usá-lo em vez disso:
SELECT * FROM MyTable
WHERE CHARINDEX('word1', Column1) > 0
AND CHARINDEX('word2', Column1) > 0
AND CHARINDEX('word3', Column1) > 0
Também, por favor, tenha em mente que este e o método na resposta aceite só cobrem a correspondência de sub-texto em vez de correspondência de palavras. Assim, por exemplo, a string 'word1word2word3'
continuaria a corresponder.
Função
CREATE FUNCTION [dbo].[fnSplit] ( @sep CHAR(1), @str VARCHAR(512) )
RETURNS TABLE AS
RETURN (
WITH Pieces(pn, start, stop) AS (
SELECT 1, 1, CHARINDEX(@sep, @str)
UNION ALL
SELECT pn + 1, stop + 1, CHARINDEX(@sep, @str, stop + 1)
FROM Pieces
WHERE stop > 0
)
SELECT
pn AS Id,
SUBSTRING(@str, start, CASE WHEN stop > 0 THEN stop - start ELSE 512 END) AS Data
FROM
Pieces
)
Query
DECLARE @FilterTable TABLE (Data VARCHAR(512))
INSERT INTO @FilterTable (Data)
SELECT DISTINCT S.Data
FROM fnSplit(' ', 'word1 word2 word3') S -- Contains words
SELECT DISTINCT
T.*
FROM
MyTable T
INNER JOIN @FilterTable F1 ON T.Column1 LIKE '%' + F1.Data + '%'
LEFT JOIN @FilterTable F2 ON T.Column1 NOT LIKE '%' + F2.Data + '%'
WHERE
F2.Data IS NULL
Em vez de SELECT * FROM MyTable WHERE Column1 CONTAINS 'word1 word2 word3'
,
adicione e entre essas palavras como:
SELECT * FROM MyTable WHERE Column1 CONTAINS 'word1 And word2 And word3'
Para mais detalhes, veja aqui https://msdn.microsoft.com/en-us/library/ms187787.aspx
Actualizar
Para seleccionar frases, use aspas duplas como:
SELECT * FROM MyTable WHERE Column1 CONTAINS '"Phrase one" And word2 And "Phrase Two"'
p. s. Você tem que ativar a pesquisa de texto completo na tabela antes de usar contém palavra-chave. para mais detalhes, veja aqui https://docs.microsoft.com/en-us/sql/relational-databases/search/get-started-with-full-text-search
SELECT * FROM MyTable WHERE
Column1 LIKE '%word1%'
AND Column1 LIKE '%word2%'
AND Column1 LIKE '%word3%'
Alterado OR
para AND
com base em Editar para questionar.
SELECT * FROM MyTable WHERE INSTR('word1 word2 word3',Column1)<>0
Servidor SQL:
CHARINDEX(Column1, 'word1 word2 word3', 1)<>0
Para obter a correspondência exacta. O exemplo (';a;ab;ac;',';b;')
não terá correspondência.
SELECT * FROM MyTable WHERE INSTR(';word1;word2;word3;',';'||Column1||';')<>0
Se estiver a usar a base de Dados Oracle , então poderá conseguir isto usando contains query. Contains querys are faster than like query.
Se precisar de todas as palavras
SELECT * FROM MyTable WHERE CONTAINS(Column1,'word1 and word2 and word3', 1) > 0
Se precisar de alguma das palavras
SELECT * FROM MyTable WHERE CONTAINS(Column1,'word1 or word2 or word3', 1) > 0
Contém Índice de necessidade do tipo contexto na sua coluna.
CREATE INDEX SEARCH_IDX ON MyTable(Column) INDEXTYPE IS CTXSYS.CONTEXT
Porque não USAR "in" em vez disso?
Select *
from table
where columnname in (word1, word2, word3)
SELECT * FROM MyTable WHERE Column1 Like "*word*"
Isto irá mostrar todos os registos onde column1
tem um valor parcial que contém word
.
Tente usar a" pesquisa de tesarus " no índice de texto completo no servidor de MS SQL. Isto é muito melhor do que usar "%" em busca se você tiver milhões de registros. tesarus tem uma pequena quantidade de consumo de memória do que os outros. tente procurar nestas funções:)
A melhor maneira é fazer um índice de texto completo numa coluna do quadro e utilizar conter em vez de
SELECT * FROM MyTable WHERE
contains(Column1 , N'word1' )
AND contains(Column1 , N'word2' )
AND contains(Column1 , N'word3' )
Uma das maneiras mais fáceis de alcançar o que é mencionado na pergunta é usando contém com perto ou '~'. Por exemplo, as seguintes consultas dar-nos-iam todas as colunas que incluem especificamente word1, word2 e word3.
SELECT * FROM MyTable WHERE CONTAINS(Column1, 'word1 NEAR word2 NEAR word3')
SELECT * FROM MyTable WHERE CONTAINS(Column1, 'word1 ~ word2 ~ word3')
Além disso, CONTAINSTABLE devolve um rank para cada documento com base na proximidade de "word1", "word2" e "word3". Por exemplo, se um documento contém a frase, "o word1 é word2 e word3", seu ranking seria alto porque o os termos estão mais próximos uns dos outros do que em outros documentos.
Uma outra coisa que gostaria de acrescentar é que também podemos usar proximity_term para encontrar colunas onde as palavras estão dentro de uma distância específica entre elas dentro da frase da coluna.
DECLARE @SearchStr nvarchar(100)
SET @SearchStr = ' '
CREATE TABLE #Results (ColumnName nvarchar(370), ColumnValue nvarchar(3630))
SET NOCOUNT ON
DECLARE @TableName nvarchar(256), @ColumnName nvarchar(128), @SearchStr2 nvarchar(110)
SET @TableName = ''
SET @SearchStr2 = QUOTENAME('%' + @SearchStr + '%','''')
WHILE @TableName IS NOT NULL
BEGIN
SET @ColumnName = ''
SET @TableName =
(
SELECT MIN(QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME))
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_TYPE = 'BASE TABLE'
AND QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME) > @TableName
AND OBJECTPROPERTY(
OBJECT_ID(
QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME)
), 'IsMSShipped'
) = 0
)
WHILE (@TableName IS NOT NULL) AND (@ColumnName IS NOT NULL)
BEGIN
SET @ColumnName =
(
SELECT MIN(QUOTENAME(COLUMN_NAME))
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = PARSENAME(@TableName, 2)
AND TABLE_NAME = PARSENAME(@TableName, 1)
AND DATA_TYPE IN ('char', 'varchar', 'nchar', 'nvarchar', 'int', 'decimal')
AND QUOTENAME(COLUMN_NAME) > @ColumnName
)
IF @ColumnName IS NOT NULL
BEGIN
INSERT INTO #Results
EXEC
(
'SELECT ''' + @TableName + '.' + @ColumnName + ''', LEFT(' + @ColumnName + ', 3630) FROM ' + @TableName + ' (NOLOCK) ' +
' WHERE ' + @ColumnName + ' LIKE ' + @SearchStr2
)
END
END
END
SELECT ColumnName, ColumnValue FROM #Results
DROP TABLE #Results
select * from table where name regexp '^word[1-3]$'
Ou
select * from table where name in ('word1','word2','word3')