【问题标题】:SQL Query to do a reverse CONTAINS search?SQL Query 执行反向 CONTAINS 搜索?
【发布时间】:2014-09-24 22:36:44
【问题描述】:

我需要搜索作为用户输入字符串的子字符串的文章标签字符串。

因此,在下面的示例中,如果用户搜索“正常”,则查询应返回第 1 条和第 3 条,因为第 3 条具有通配符标签“norm*”。 如果我搜索“规范化”,那么我应该返回第 3 和第 4 条。 如果我需要更清楚地解释我的问题,请告诉我。

例子-

  • 第 1 条标签 = 正常
  • 第 2 条标签 = 苹果
  • 第 3 条标签 = norm*
  • 第 4 条标签 = 规范化
  • 第 5 条标签 = 护卫舰

注意 - 我只需要对以 * 结尾的标签进行子字符串搜索

【问题讨论】:

  • 你在哪个数据库中?这可能更复杂,因为 '%' 类似于通配符
  • select * from article where id not in (select id from article where tag like "foo")
  • 正则表达式和通配符不能混用。
  • 你能把数据分解成#3 是两列吗:norm | true 和 #1 是 normal | false

标签: sql regex


【解决方案1】:

最简单但可能不是最有效的方法是将表中的所有* 替换为% 并使用LIKE 声明:

SELECT
  Tag
FROM
  Article
WHERE
  'normal' LIKE REPLACE(Tag, '*', '%')

查看SqlFiddle中的示例

【讨论】:

  • +1 聪明,性能比我糟糕的解决方案更好。我考虑过这个,但认为它行不通,所以我从未尝试过;)
  • 谢谢,这似乎可以在 SqlFiddle 中使用,希望它可以在 Sqlite(win8 通用应用程序)中使用。用 %norm 和 %norm% 试过了,它似乎在所有情况下都能正常工作。
【解决方案2】:

我认为这个查询应该可以工作,尽管我没有在您的示例数据之外对其进行测试。

另外,你没有指定你正在使用什么数据库,我只是在 MS SQL 上尝试过,但它应该很容易适应其他数据库,因为它只依赖于 charindex 和 left(或 substring)以及那些函数应该在大多数数据库上都可用。

SQL Fiddle

MS SQL Server 2008 架构设置

create table your_table (article varchar(10), tag varchar (20))
insert your_table values 
('Article 1','normal'),
('Article 2','apple'),
('Article 3','norm*'),
('Article 4','normalization'),
('Article 5','corvette')

查询 1

declare @str varchar(30) = 'normalization'

select t.article, tag 
from your_table t
left join (
    select 
       article, 
       left(tag, charindex('*', tag,0)-1) t, 
       charindex('*', tag,0)-1 as l 
    from your_table 
    where charindex('*', tag,0) > 0
    ) a
on t.article = a.article
where (tag = @str) or (left(@str, l) = t)

Results

|   ARTICLE |           TAG |
|-----------|---------------|
| Article 3 |         norm* |
| Article 4 | normalization |

查询 2

declare @str varchar(30) = 'normal'

select t.article, tag 
from your_table t
left join (
    select 
       article, 
       left(tag, charindex('*', tag,0)-1) t, 
       charindex('*', tag,0)-1 as l 
    from your_table 
    where charindex('*', tag,0) > 0
    ) a
on t.article = a.article
where (tag = @str) or (left(@str, l) = t)

Results

|   ARTICLE |    TAG |
|-----------|--------|
| Article 1 | normal |
| Article 3 |  norm* |

【讨论】:

  • 这是我认为的唯一解决方案,但我认为如果客户端最终输入大量数据会很慢。如果 psadac 在 sqlite 中不起作用,我会尝试这个答案。有选择总是很棒的!谢谢。
【解决方案3】:

如果您使用 SQL Server,那么您可以这样做: 我是说 如果以*结尾,则检查子串是否存在, 否则直接匹配

    SELECT * FROM Articles
    WHERE
    CASE WHEN RIGHT(Articles.Tag, 1) = '*'
        CHARINDEX(LEFT(Articles.Tag, LEN(Articles.Tag) - 1), GivenStr)
    ELSE
        Articles.Tag=GivenStr

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-10-08
    • 1970-01-01
    • 1970-01-01
    • 2023-03-16
    • 1970-01-01
    • 2014-04-14
    • 2020-04-02
    • 2013-12-15
    相关资源
    最近更新 更多