【问题标题】:Search functionality with LIKE operator over several columns使用 LIKE 运算符在多列上搜索功能
【发布时间】:2014-03-04 15:12:17
【问题描述】:
  • 我有一个搜索字段,允许用户输入空格分隔字词。
  • 我需要从数据库中的几个表中搜索5列中的每个单词。
  • 我想创建一个可以从我的C# Web 服务(实体框架)调用的数据库函数

目前,我使用这个:

CREATE FUNCTION [dbo].[SEARCH_SINGLE] (
    @langId INT = 4,
    @searchString VARCHAR(MAX) = NULL
)
RETURNS TABLE
AS
RETURN
    WITH words AS (
        SELECT * FROM [dbo].splitstring(@searchString, ' ')
    )
    SELECT DISTINCT
        ...
    FROM
        ...
    WHERE
        ...
        AND (
            EXISTS(SELECT t2.Name FROM words t2 WHERE a.[FIRSTNAME] like '%'+t2.Name+'%')
            OR EXISTS(SELECT t2.Name FROM words t2 WHERE a.[LASTNAME] like '%'+t2.Name+'%')
            OR EXISTS(SELECT t2.Name FROM words t2 WHERE c.[CITY] like '%'+t2.Name+'%')
            OR EXISTS(SELECT t2.Name FROM words t2 WHERE j.[PROMO_YEAR] like '%'+t2.Name+'%')
            OR EXISTS(SELECT t2.Name FROM words t2 WHERE e.[EMPLOYOR] like '%'+t2.Name+'%')
        )

它有效,但它返回匹配一个输入的单词的所有记录。 我需要返回匹配至少一列中的所有单词的记录。

例如,如果我们只考虑firstnamelastname

  • “John”应返回“John Doe”、“John Bieber”、“John Daney”等。
  • “John D%”应返回“John Doe”和“John Daney”
  • “John Doe”应该只返回“John Doe”。

实际上,对于像“John Doe McDonald”这样的搜索,我需要像这样模拟WHERE

WHERE 
    (
        a.[FIRSTNAME] like '%John%'
        OR a.[LASTNAME] like '%John%'
        OR c.[CITY] like '%John%'
        OR j.[PROMO_YEAR] like '%John%'
        OR e.[EMPLOYOR] like '%John%'
    ) 
    AND (
        a.[FIRSTNAME] like '%Doe%'
        OR a.[LASTNAME] like '%Doe%'
        OR c.[CITY] like '%Doe%'
        OR j.[PROMO_YEAR] like '%Doe%'
        OR e.[EMPLOYOR] like '%Doe%'
    )
    AND (
        a.[FIRSTNAME] like '%McDonald%'
        OR a.[LASTNAME] like '%McDonald%'
        OR c.[CITY] like '%McDonald%'
        OR j.[PROMO_YEAR] like '%McDonald%'
        OR e.[EMPLOYOR] like '%McDonald%'
    )

理想情况下,如果在整个数据库的 5 列中都没有找到某个单词,则只需忽略它(“John Doe sjdhf67df”应该返回“John Doe”...)。

我尝试动态构建查询,但在返回结果时遇到了一些问题,因为我们不能在函数中使用 EXEC...

我们目前考虑全文搜索

如何修改我的函数以获得预期结果?

【问题讨论】:

  • “我们暂时不考虑全文搜索!”。为什么不呢?
  • 我被要求创建一个简单的搜索功能,而无需在数据库级别(索引等)进行太多修改。由于搜索是跨多个表完成的,所以我在网上看到的内容让我觉得这是很多工作。
  • 我几乎不会认为您的要求很简单。尝试解析单个条目并检查空格、通配符等,然后知道将各个部分应用于哪个列听起来很痛苦。修改前端是一种选择吗?如果您可以让您的用户选择他们想要搜索的字段并输入一个单词,这将更容易。如果他们想搜索多个字段,让他们能够添加更多搜索条件。
  • 我们已经有一个“自定义搜索”,用户可以在其中选择他们想要搜索的字段。但要求是有第二个“简单搜索”,允许用户使用单个文本字段进行搜索。老实说,我目前有一个使用完整 C#、LINQ 和实体框架的工作解决方案,但我想以数据库方式进行。

标签: sql sql-server function search sql-like


【解决方案1】:

我终于回到了以下解决方案:

CREATE FUNCTION [dbo].[SEARCH_SINGLE] (
    @langId INT = 4,
    @searchString VARCHAR(MAX) = NULL
)
RETURNS TABLE
AS
RETURN
    WITH
words AS (
    SELECT * FROM [dbo].splitstring(@searchString, ' ')
),
results AS (
    SELECT DISTINCT
        a.[ID] as Id,
        a.[LASTNAME] as LastName,
        a.[FIRSTNAME] as FirstName,
        d.[COUNTRY_LABEL] as CountryLabel,
        c.[CITY] as City,
        j.[PROMO_YEAR] as PromoYear,
        CASE WHEN EXISTS(SELECT t2.Name FROM words t2 WHERE a.[FIRSTNAME] like '%'+t2.Name+'%') THEN 1 ELSE 0 END +
        CASE WHEN EXISTS(SELECT t2.Name FROM words t2 WHERE a.[LASTNAME] like '%'+t2.Name+'%') THEN 1 ELSE 0 END +
        CASE WHEN EXISTS(SELECT t2.Name FROM words t2 WHERE c.[CITY] like '%'+t2.Name+'%') THEN 1 ELSE 0 END +
        CASE WHEN EXISTS(SELECT t2.Name FROM words t2 WHERE j.[PROMO_YEAR] like '%'+t2.Name+'%') THEN 1 ELSE 0 END +
        CASE WHEN EXISTS(SELECT t2.Name FROM words t2 WHERE e.[EMPLOYOR] like '%'+t2.Name+'%') THEN 1 ELSE 0 END as Nb
    FROM
        ...
    WHERE
        ...
)
SELECT 
    Id,
    LastName,
    FirstName,
    CountryLabel,
    City,
    PromoYear,
FROM
    results
WHERE
    Nb = (SELECT MAX(Nb) FROM results)
    AND Nb <> 0
  • 我在每一列中搜索每个单词。
  • 我为每条记录打分。
  • 我只返回得分最高的记录。

它似乎满足了我的所有要求。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-09-21
    • 1970-01-01
    • 2018-11-02
    • 1970-01-01
    • 2017-03-15
    • 2011-07-08
    • 2019-08-24
    • 2021-12-11
    相关资源
    最近更新 更多