SQL Server-选择关键字和同义词列表

如何解决SQL Server-选择关键字和同义词列表

| 我有两个表: 关键词 我在其中存储唯一关键字。
CREATE TABLE [dbo].[Keywords]
[KeywordID] [int] IDENTITY(1,1) NOT NULL,[Description] [varchar](200) NOT NULL

select * from Keywords   

  1 MVC  
  2 HTML  
  3 C#  
  4 ASP.NET MVC  
  5 MVC3
关键字同义 我指出某些关键字是其他关键字的同义词。
CREATE TABLE [dbo].[KeywordSynonymous]
    [KeywordID] [int] NOT NULL,[KeywordSynonymousID] [int] NOT NULL
这两个字段在关键字表中均为FK,并且两个组合字段均在此表中用作PK。 在这里,我要声明\'MVC \'和\'MVC3 \'是同义词,也许\'MVC3 \'和\'ASP.NET MVC \'也是同义词。
select * from KeywordSynonymous  

1 5  
5 4  
概念 1) 如果关键字\'MVC \'是\'MVC3 \'的同义词 和\'MVC3 \'是\'ASP.NET MVC \'的同义词        那么从概念上讲MVC也是\'ASP.NET MVC \'的同义词    2) 如果关键字\'MVC \'是\'MVC3 \'的同义词        那么VICEVERSA也是正确的,并且'MVC3是''MVC \'的同义词    题 想象一下,在我的网站上,我正在搜索并且用户可以键入任何内容,但是对于我们的示例,他可以键入\'MVC \'或\'MVC3 \'... 如何使用一条SQL语句获得所有可能的同义词,以确保同时满足Concept 1和Concept 2? 意思是:
>> if the user types \'MVC\',my sql should return \'MVC,MVC3\',\'ASP.NET MVC\'.  
>> if the user types \'MVC3\',\'ASP.NET MVC\'.  
>> if the user types \'ASP.NETMVC\',\'ASP.NET MVC\'.  
================================================== ============== 更新 我觉得我必须添加一些关于我正在开发的网站的信息。在这个市场上,年轻的专业人​​员将能够使用新的方式来推销自己的服务。 由于我们想允许任何职业,所以我目前无法预见什么“关键词”将更好地定义每个职业。因此,我将允许用户定义这些关键字。 我的问题是我需要允许UserX按专业和关键字搜索这些年轻的专业人​​员。我需要允许这些用户将其搜索到的关键字与现有关键字进行匹配,以便当前和将来的搜索将自动匹配正确的配置文件。 这就是为什么我事先没有所有关键字,并且肯定无法识别将来的关键字及其各自的同义词的原因。我也不能期望用户将所有现有关键字匹配到所有相关关键字...所以这就是为什么我需要Concept 1工作的原因。 ================================================== ============== 堆栈溢出标签 关键字的模块应该与StackOverflow标记(关键字)非常相似,如果我将TAGS设置为SQL,则正在搜索TSQL或SQL SERVER的人...也应该看到这篇文章。 :-)     

解决方法

您绝对应该使用通用表表达式。这是解决您问题的理想解决方案,因为它不会更改您当前的数据库架构,而且最重要的是,由于
KeywordSynonymous
表具有递归性,CTE是一种优雅且合乎逻辑的解决方案。 为此,最好先创建一个视图,该视图在两个方向上选择KeywordSynonymous中的所有行。在您的情况下,该表返回行
select * from KeywordSynonymous  

1 5  
5 4  
下面的视图将显示
select * from KeywordSynonymousAll   

1 5      0   
2 NULL   0
3 NULL   0
4 NULL   0
4 5      1
5 1      1
5 4      0
该视图是将简化递归查询的数据结构。它添加了第三列以标识何时进行了还原。这是满足您的概念编号2所必需的。 因此,这里是视图:
create view KeywordSynonymousAll as
    select KeywordID,KeywordSynonymousID,0 as reversed
      from KeywordSynonymous
     union
    select K.KeywordID,null as KeywordSynonymousID,0 as reversed
      from Keywords K
     where not exists(select null
                        from KeywordSynonymous
                       where KeywordID = K.KeywordID)
     union
     select KeywordSynonymousID,KeywordID,1 as reversed
       from KeywordSynonymous
和查询
declare @search varchar(200);

set @search = \'MVC3\'; -- TEST HERE for different search keywords

with Synonymous (keywordID,SynKeywordID) as ( 

    -- initial state: Get the keywordId and KeywordSynonymousID for the description as @search
    select K.keywordID,KS.KeywordSynonymousID
      from Keywords K
     inner join KeywordSynonymous KS on KS.KeywordID = K.keywordId
     where K.Description = @search

    union all

    -- also initial state but with reversed columns (because we want lookup in both directions)
    select KS.KeywordSynonymousID,K.keywordID
      from Keywords K
     inner join KeywordSynonymous KS on KS.KeywordSynonymousID = K.keywordId
     where K.Description = @search

     union all

    select S.SynKeywordID,KS.KeywordSynonymousID
      from Synonymous S
     inner join KeywordSynonymousAll KS on KS.KeywordID = S.SynKeywordID
     where KS.reversed = 0 -- to avoid infinite recursion

     union all

    select KS.KeywordSynonymousID,S.SynKeywordID 
      from Synonymous S
     inner join KeywordSynonymousAll KS on KS.KeywordID = S.KeywordID
     where KS.reversed = 1 -- to avoid infinite recursion

) 

-- finally output the result
select distinct K.Description
  from Synonymous S
 inner join Keywords K on K.KeywordID = S.keywordID
对于
set @search = \'MVC3\'
,结果集为
  ASP.NET MVC
  MVC
  MVC3
set @search = \'MVC\'
set @search = \'ASP.NET MVC\'
发生相同的结果集 对于
set @search = \'C#\'
set @search = \'HTML\'
,您一无所有 编辑 在我以前的文章中,我说对于C#和HTML,结果集将为空。如果您还想返回这些值,则将查询的最后一部分更改为:
-- finally output the result
select distinct T.Description
  from (
    select K.Description
      from Synonymous S
     inner join Keywords K on K.KeywordID = S.keywordID

    union

    select Description
      from Keywords
     where Description = @search) T
现在,对于
set @search = \'C#\'
,结果集为
  C#
对于
set @search = \'HTML\'
,结果集为
  HTML
希望这可以帮助     ,要达到至少#1,您可以使用递归公用表表达式(CTE) 这里的定义     ,由于您的条件(概念),同义词表未规范化。这是问题的主要根源,也是解决问题所需的复杂查询/触发器。 我会保留关键字表:
CREATE TABLE [dbo].[Keywords]
[KeywordID] [int] IDENTITY(1,1) NOT NULL,[Description] [varchar](200) NOT NULL

select * from Keywords   

  1 MVC  
  2 HTML  
  3 C#  
  4 ASP.NET MVC  
  5 MVC3
  6 C sharp
使同义表有所不同:
CREATE TABLE [dbo].[KeywordSynonymity]
    [SynonymityID] [int] NOT NULL,[KeywordID] [int] NOT NULL

select * from KeywordSynonymous  

1 1               --- for the 1 (MVC) and 5 (MVC3)
1 5               --- being synonymous
2 3               --- for the 3 (C#) and 6 (C sharp)
2 6               --- being synonymous
然后要加上
MVC3
ASP.NET MVC
也是同义词,您只需在“同义词”表中添加一行(1,4)。 如果这样-由于未知的原因,但尽管如此-您想将
MVC3
C#
组合为同义词,则必须将所有SynonymityID = 2(与C#相同)的行更改为= 1(与MVC相同)。 但是,随着表格的标准化,所有查询将变得更加简单。     ,1称为对称关系,2称为传递关系。 我建议您在添加新关键字时对其进行维护。您可以这样操作。将关键字添加到数据库后,如果尚无同义词,则将其指定为\“ master \”关键字。否则,将新关键字链接到现有的主关键字。 这是一个以这种方式添加新关键字的存储过程:
CREATE PROCEDURE [dbo].[AddKeyword] 
    @newKeyword [varchar](200),@synonymKeyword [varchar](200) = NULL
AS
BEGIN
    SET NOCOUNT ON;

    set transaction isolation level serializable

    begin transaction

        if EXISTS (select 1 from Keywords where [Description] = @newKeyword)
        begin
            commit transaction
            return
        end

        declare @masterKeywordId int

        select 
            @masterKeywordId = ISNULL(KeywordSynonymous.KeywordID,Keywords.KeywordID) 
        from
            Keywords
        left join
            KeywordSynonymous
        on
            Keywords.KeywordID = KeywordSynonymous.KeywordSynonymousID
        where
            [Description] = @synonymKeyword

        insert into Keywords VALUES (@newKeyword)

        if @masterKeywordId is not null
            insert into KeywordSynonymous VALUES (@masterKeywordId,SCOPE_IDENTITY())

    commit transaction

END
在此存储过程中,您传递了一个要添加的新关键字,还可以选择还传递一个已知的同义词。此同义词不必是\“ master \”。如果存在,则会查找其\“ master \”关键字ID,并将新创建的关键字与该\“ master \” ID链接起来。 这是最终选择所有它们的方式:
CREATE PROCEDURE [dbo].[GetSynonymKeywords]
    @keyword [varchar](200)
AS
BEGIN
    SET NOCOUNT ON;

    declare @masterKeywordId int

    select 
        @masterKeywordId = ISNULL(KeywordSynonymous.KeywordID,Keywords.KeywordID) 
    from
        Keywords
    left join
        KeywordSynonymous
    on
        Keywords.KeywordID = KeywordSynonymous.KeywordSynonymousID
    where
        [Description] = @keyword

    select 
        KeywordId,[Description]
    from
        Keywords
    where
        KeywordId = @masterKeywordId
    union
    select 
        Keywords.KeywordId,[Description]
    from
        KeywordSynonymous
    join
        Keywords
    on
        KeywordSynonymous.KeywordSynonymousID = Keywords.KeywordId
    where
        KeywordSynonymous.KeywordId = @masterKeywordId

END
该存储过程首先找到给定传递关键字的关键字ID。然后,它为该ID查找\“ master \”关键字。然后,它返回master关键字以及与此master关键字同义的所有关键字。 添加新单词的示例:
EXEC [dbo].[AddKeyword] @newKeyword = N\'MVC\'
EXEC [dbo].[AddKeyword] @newKeyword = N\'ASP.NET MVC\',@synonymKeyword = \'MVC\'
EXEC [dbo].[AddKeyword] @newKeyword = N\'MVC3\',@synonymKeyword = \'ASP.NET MVC\'
请注意,您可以在第三行中将\'MVC \'指定为同义词,它也可以正常工作。 检索关键字的示例:
[dbo].[GetSynonymKeywords]  @keyword = N\'MVC3\'
[dbo].[GetSynonymKeywords]  @keyword = N\'ASP.NET MVC\'
[dbo].[GetSynonymKeywords]  @keyword = N\'MVC3\'
这三个都返回相同的值列表。 我在AddKeyword SP中将隔离级别序列化,以确保没有并发问题可以根据您的并发模型随意修改,序列化可能不适合您。 如果您愿意,也可以将GetMasterId(在两个SP中出现的块)拉出到UDF中,或者进行其他适合您特定情况的修改。     ,好的,那这个呢?
DECLARE @TempKeywordID TABLE (KeywordID int)
INSERT INTO @TempKeywordID (KeywordID)(select KeywordID from Keywords where [Description] = @SearchKeyword)

DECLARE @intFlag INT
SET @intFlag = 1

WHILE (@intFlag <=(Select Count(KeywordSynonymousID) from KeywordSynonymous)) --Loop for all records in KeywordSynonymous
BEGIN
    INSERT INTO @TempKeywordID (KeywordID)(Select KeywordSynonymousID from KeywordSynonymous where KeywordID in (Select KeywordID from @TempKeywordID))
    INSERT INTO @TempKeywordID (KeywordID)(Select KeywordID from KeywordSynonymous where KeywordSynonymousID in (Select KeywordID from @TempKeywordID))    

    SET @intFlag = @intFlag + 1
END

SELECT * FROM Keywords WHERE KeywordID IN (SELECT * FROM @TempKeywordID)
    

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 &lt;select id=&quot;xxx&quot;&gt; SELECT di.id, di.name, di.work_type, di.updated... &lt;where&gt; &lt;if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 &lt;property name=&quot;dynamic.classpath&quot; value=&quot;tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-