搜索字符串并有条件地忽略连字符

时间:2018-11-09 10:07:54

标签: sql string substring sql-like

关键字:usedredcars

我要列出这些行;

used-red-cars-florida  
used-redcars-florida  
usedred-cars-florida  
usedredcars-florida  

编辑:我想列出所有包含关键字+破折号+%(其他)的行

usedredcars-%
和二手车可以包含任何破折号

u-s-e-d-r-edcars-%  
used-r-e-dcars-%  
usedred-c-a-r-s-%  

查询,

SELECT * FROM [TABLE]
where description LIKE keyword+'-%'  

我只能得到;

usedredcars-florida

我不想要这个;

used-redcarsflorida
usedredcarsflorida
usedred-carsflorida

我应该如何修改查询?

谢谢

更多示例数据;

关键字:fullstack

完整堆栈
全栈
全栈学院
全栈应用的
fullstackbigdata-com
全栈数据
fullstack-dev
全栈开发人员职位
fullstack-digital-agency
全栈执行文件
满满的节日
全胶卷
全额融资
全栈自由职业者
fullstack-it-solutions
fullstack-labs
全面营销
全栈营销
墨西哥全栈
全栈投资组合
满堆pty-ltd
完整堆栈资源
fullstack-ro
全栈服务
完整解决方案
fullstacksolutions.com
全栈人员编制
fullstackstud-io
fullstack-support
全栈技术
满栈托龙托

例如在这里,我要丢弃所有粗体

3 个答案:

答案 0 :(得分:1)

(此答案假设您正在使用SQL Server)

我认为您可以通过一次替换一个-来解决该问题,看看是否可以找到与关键字完全匹配的内容:

DECLARE @t TABLE (id int, keyword VARCHAR(8000));
INSERT INTO @t VALUES
(1, 'usedredcars'),
(2, 'used-redcars'),
(3, 'usedred-cars'),
(4, 'used-red-cars'),
(5, 'florida-usedredcars'),
(6, 'usedredcars-florida'),
(7, 'florida-usedredcars-florida'),
(8, 'rarelyused-red-cars'),
(9, 'used-red-carshops');

WITH cte AS (
    -- pad the seed string with hyphens to simplify edge case handling
    SELECT id, keyword, '-' + keyword + '-' AS search
    FROM @t AS base

    UNION ALL

    -- replace hyphens from the middle one at a time
    SELECT id, keyword, STUFF(search, CHARINDEX('-', search, 2), 1, '')
    FROM cte AS prev
    WHERE NULLIF(CHARINDEX('-', search, 2), LEN(search)) > 0

    -- BE ADVISED that STUFF can return unexpected size varchar and thus:
    -- Types don't match between the anchor and the recursive part
    -- explicitly cast the result to desired size if that happens
)
SELECT *
FROM cte
WHERE search LIKE '%-usedredcars-%'

DB Fiddle

答案 1 :(得分:0)

我在打电话,所以这是伪代码...

    @transaction.atomic
    def form_valid(self, form):
        self.instance = form.save(commit=False)
        self.instance.event = self.request.event
        # When the super method is called the instance
        # is saved because it's a model form
        super().form_valid(form)
        return HttpResponseRedirect(self.get_success_url())

将正确排除 SELECT * FROM [table] WHERE REPLACE('-', '', description) LIKE keyword + '%' AND description LIKE REPLACE(keyword, '%-', REPLACE('-', '', description)) ,但不包括used-red-carflorida

这是我在Ansi SQL中能做的最好的事情。

答案 2 :(得分:0)

由于您未指定DBMS,因此将其视为Oracle。
这不是一个非常优雅的解决方案,但它应该可以工作:

首先创建一个将关键字转换为正则表达式的函数:

CREATE OR REPLACE FUNCTION keyword2re
(
  p_kw IN VARCHAR2
)
RETURN VARCHAR2
AS
  v_result VARCHAR2(1000);
  v_length INTEGER;
  v_count  INTEGER;
BEGIN

  v_length := LENGTH(p_kw);
  FOR v_count IN 1..v_length LOOP
    v_result := v_result || '[\-]*' || SUBSTR(p_kw, v_count, 1);
  END LOOP;
  v_result := v_result || '([\-].*)?$';
  RETURN v_result;

END keyword2re;

它在每个字符之前都带有可选的破折号,并表示最终的剩余部分应以破折号开头。

所以

used

成为

[\-]*u[\-]*s[\-]*e[\-]*d([\-].*)?$

之后执行查询

SELECT *
FROM   my_table
WHERE  REGEXP_LIKE(description, keyword2re('fullstack'));