当前位置: 首页 > 面试题库 >

SQL查询以查找具有最匹配关键字的行

韦胜泫
2023-03-14
问题内容

我真的很不擅长SQL,我想知道我可以使用哪种SQL解决这个问题,在这个问题以下我怀疑是NP完全问题,但是我认为查询需要很长时间才能在大型数据集上运行因为这将作为后台任务完成。首选标准sql语句,但是如果需要存储过程,则使用它。SQL必须在Postgres
9.3上运行。

问题:给定一组包含一组关键字的文章,请为每条包含最多匹配关键字的文章查找前n条文章。

文章表的精简版本如下所示:

CREATE TABLE article (
  id character varying(36) NOT NULL,  -- primary key of article
  keywords character varying,         -- comma separated set of keywords

  CONSTRAINT pk_article PRIMARY KEY (id)
);

-- Test Data
INSERT INTO article(id, keywords) VALUES(0, 'red,green,blue');
INSERT INTO article(id, keywords) VALUES(1, 'red,green,yellow');
INSERT INTO article(id, keywords) VALUES(2, 'purple,orange,blue');
INSERT INTO article(id, keywords) VALUES(3, 'lime,violet,ruby,teal');
INSERT INTO article(id, keywords) VALUES(4, 'red,green,blue,yellow');
INSERT INTO article(id, keywords) VALUES(5, 'yellow,brown,black');
INSERT INTO article(id, keywords) VALUES(6, 'black,white,blue');

这将导致以下SELECT * FROM article;查询:

Table: article
------------------------
id  keywords            
------------------------
0   red,green,blue      
1   red,green,yellow    
2   purple,orange,blue  
3   lime,violet,ruby,teal
4   red,green,blue,yellow
5   yellow,brown,black
6   black,white,blue

假设我想为每条包含最多匹配关键字的文章查找前三篇文章,则输出应为:

------------------------
id  related
------------------------
0   4,1,6
1   4,0,5
2   0,4,6
3   null
4   0,1,6
5   1,6
6   5,0,4

问题答案:

就像@a_horse一样:使用规范化的设计会更简单(除了使其他任务更简单/更简洁),但
仍然不简单

另外,数据类型的PK列character varying(36)高度可疑(且效率低下),并且很可能应该是integer类型,或者至少应该是类型uuid

这是根据您的 设计的 一种可能的解决方案 ,如下所示

WITH cte AS (
   SELECT id, string_to_array(a.keywords, ',') AS keys
   FROM   article a
   )
SELECT id, string_agg(b_id, ',') AS best_matches
FROM  (
   SELECT a.id, b.id AS b_id
        , row_number() OVER (PARTITION BY a.id ORDER BY ct.ct DESC, b.id) AS rn
   FROM   cte a
   LEFT   JOIN cte b ON a.id <> b.id AND a.keys && b.keys
   LEFT   JOIN LATERAL (
      SELECT count(*) AS ct
      FROM  (
         SELECT * FROM unnest(a.keys)
         INTERSECT ALL
         SELECT * FROM unnest(b.keys)
         ) i
      ) ct ON TRUE
   ORDER  BY a.id, ct.ct DESC, b.id  -- b.id as tiebreaker
   ) sub
WHERE  rn < 4
GROUP  BY 1;

SQL Fiddleid改为使用整数)。

CTEcte将字符串转换为数组。您甚至可以拥有像这样的功能性GIN索引…

如果在前3个选择中有多行并列,则需要定义一个 _ 决胜局_ 。在我的示例中,较小的行排在id第一位。

比较是在JSON数组和SQL数组之间进行的,但它基本上是相同的问题,需要解决相同的问题。还比较了两个类似的选择。

为了加快速度,您至少应该在数组列上有一个GIN索引(而不是用逗号分隔的字符串),并且查询不需要CTE步骤。完全归一化的设计还有其他优点,但不一定比具有GIN索引的数组更快。



 类似资料:
  • 问题内容: 我目前正在做类似物物交换系统的系统。这样的情况。客户(茉莉花)需要输入“ NAME”属性(她必须寻找的内容)并输入“ SEEK”属性(她需要寻找的内容)。为了获得结果,“ SEEK”属性必须与其他客户的“名称”属性匹配,而其他客户的“ SEEK”属性必须与Jasmine的“ HAVE”属性匹配。 例如我有表项(已经在数据库中) 例如,茉莉花具有“名称”属性的耳机和“搜索”属性的笔记本电

  • 问题内容: 如果我有一个看起来像这样的表: 还有一个THINGS表,如下所示: 我正在尝试提出一个纯SQL查询,该查询可以让我找出什么可以访问什么。基本上,我想要一个看起来像这样的查询: 并返回“ John”和“ Mary”。关键是访问事物所需的许可数量是任意的。 我觉得这应该很明显,但是我无法提出一个优雅的解决方案。首选与Oracle兼容的解决方案。 编辑: Kosta和JBrooks的解决方案

  • 问题内容: 我从查询中返回了要按最佳匹配顺序进行排序的结果列表。我会尽我所能地保持清晰,但是如果某些事情还不够清晰,请告诉我,我将尝试使其更加清晰。 用户已经输入了名为的设置列表。有了这些,我正在寻找产品。一切顺利,直到他应该挑选出最佳比赛。 有几个字段,例如。 我要订购。例如,他需要先订购带有的产品,然后再订购。您可以使用来做到这一点,但是我希望不安静匹配的结果也只显示在列表的底部。因此,基本上

  • 问题内容: 我正在使用SQL Server 2005。 我只需要找出在``ody’‘栏中有特殊字符的那些行。在以下情况下,结果应仅是TemplateID = 2的行。我们如何为此编写查询? 除了以下内容,此情况下的其他任何字符都是特殊字符 问题答案: 方括号之间的内容是数字(0-9),小写字母(az),大写字母(AZ)和空格。其中的“ ^”表示“不”。请注意,这与“不喜欢’%[0-9a-zA-Z]

  • 您能建议如何在Spring Data JPA存储库中编写查询吗?情况是这样的:我有两个实体:客户和产品,关系为“OneToMany”——意味着一个客户可能有多个产品。在代码中,看起来客户实体已经设置了产品,产品引用了客户,非常简单。如果我从DB JSON中检索Customer,将如下所示: 问题是,我如何向DB写入查询,以查找其产品与通过产品集合的产品匹配的所有客户?例如,我想找到所有拥有type

  • 问题内容: 在node.js中,我可以列出具有通配符匹配的文件吗? 在fs文档中找不到通配符匹配的信息。 问题答案: Node核心未涵盖此范围。您可以检查该模块的内容。npmjs.org还是查找各种模块的绝佳资源。 用法