问题描述: 数据库中某表(article表)有五条记录,标题(title)如下: 
1、上海哪有好吃的川菜? 
2、想吃川菜了,哪里有? 
3、请告诉我上海徐家汇地区好吃的川菜? 
4、什么东西最好吃? 
5、上海的天气怎么样? 待搜索的多关键字为:上海   徐家汇   川菜 可以看到: 
第一条记录的标题可以匹配到两个关键字,“上海   川菜”; 
第二条记录的标题可以匹配到一个关键字,“川菜”; 
第三条记录的标题可以匹配到三个关键字,“上海   徐家汇   川菜”; 
第四条记录的标题不能匹配到任何一个关键字; 
第五条记录的标题可以匹配到一个关键字,“上海”; 那么,在显示查询结果的时候,要求按对关键字匹配数,由多到少排列显示,即按如下的顺序显示: 搜索“上海   徐家汇   川菜”,结果如下: 3、请告诉我上海徐家汇地区好吃的川菜? 
1、上海哪有好吃的川菜? 
2、想吃川菜了,哪里有? 
5、上海的天气怎么样? 
(其中2和5的顺序没有关系,因为它们都只能匹配到一个关键字) 这样就能模糊查询模糊查询模糊查询把最匹配查询关键字的结果放在前面显示,由多到少,而只能匹配到其中任何一个关键字的记录放在后在显示。 请问用纯SQL语句怎么实现这样的需求,不能用存储过程和临时表等其它方法。

解决方案 »

  1.   

    2 中方法
    1 使用全文索引
    2
    见代码
    CREATE TABLE tb (ID INT IDENTITY(1,1),VALUE VARCHAR(100))
    INSERT tb SELECT '中国'
    UNION ALL SELECT '中国人'
    UNION ALL SELECT '中国人民'
    UNION ALL SELECT '日本'
    UNION ALL SELECT '日本人'
    UNION ALL SELECT '我的心中有人姑娘'
    UNION ALL SELECT '人民网'
    UNION ALL SELECT '中国是个伟大的国家'
    UNION ALL SELECT '我们都是中国人,都是炎黄子孙,都是龙人传人'DECLARE @searchSTR VARCHAR(20)
    SET @searchSTR='中国人'
    SELECT ID,VALUE FROM tb a 
    INNER JOIN fn_SplitStringToROWS(@searchSTR) b
        ON CHARINDEX(b.v,a.VALUE)>0
        WHERE VALUE LIKE '%[中国人]%' 
        GROUP BY ID,VALUE
        ORDER BY COUNT(DISTINCT v) DESC
        
    DROP TABLE tb
    --附函数
    CREATE FUNCTION fn_SplitStringToROWS
    (
    @str VARCHAR(100)
    )
    RETURNS @t TABLE(v VARCHAR(2))
    AS
    BEGIN
        DECLARE @i INT
        SET @i=1
        WHILE @i<=LEN(@str)4
            BEGIN
                INSERT @t SELECT SUBSTRING(@str,@i,1)
                SET @i=@i+1
            END
        RETURN
    END
    /*
    (所影响的行数为 9 行)ID          VALUE                                                                                                
    ----------- ---------------------------------------------------------------------------------------------------- 
    9           我们都是中国人,都是炎黄子孙,都是龙人传人
    2           中国人
    3           中国人民
    8           中国是个伟大的国家
    1           中国
    6           我的心中有人姑娘
    7           人民网
    5           日本人(所影响的行数为 8 行)*/--如果要实现匹配度排序,那么可以去掉 WHERE ... LIKE那句,多余
    --
    --如果只想实现模糊的匹配,那么可以不需要连表,直接
    --
    --SELECT ID,VALUE FROM tb  WHERE VALUE LIKE '%[中国人]%' 即可.
    --
    -- 
    --
    -- 
    --
    --按词匹配. create function f_splitIDX(@SourceSql varchar(8000),@StrSeprate varchar(10))
    returns @temp table(id int identity(1,1),v varchar(100))begin
        declare @i int
        set @SourceSql=rtrim(ltrim(@SourceSql))
        set @i=charindex(@StrSeprate,@SourceSql)
        while @i>=1
        begin
            insert @temp values(left(@SourceSql,@i-1))
            set @SourceSql=substring(@SourceSql,@i+1,len(@SourceSql)-@i)
            set @i=charindex(@StrSeprate,@SourceSql)
        end
        if @SourceSql<>'\'
           insert @temp values(@SourceSql)
        return 
    end
    CREATE TABLE tb (ID INT IDENTITY(1,1),VALUE VARCHAR(100))
    INSERT tb SELECT '中国'
    UNION ALL SELECT '中国人,中国'
    UNION ALL SELECT '中国,中国人'
    UNION ALL SELECT '中国人民'
    UNION ALL SELECT '中国'
    UNION ALL SELECT '日本'
    UNION ALL SELECT '日本人'
    UNION ALL SELECT '我的心中有人姑娘'
    UNION ALL SELECT '人民网'
    UNION ALL SELECT '中国是个伟大的国家'
    UNION ALL SELECT '我们都是中国人,都是炎黄子孙,都是龙人传人'
    DECLARE @searchSTR VARCHAR(20)
    SET @searchSTR='中国人 中国'SELECT a.ID,VALUE FROM tb a
        INNER JOIN dbo.f_splitIDX(@searchSTR,' ') b
        ON CHARINDEX(v,VALUE)>0
        GROUP BY a.ID,Value
        ORDER BY COUNT(DISTINCT v) DESC,MIN(b.id),a.idDROP TABLE tb