1

MRE

CREATE TABLE `publications` (
  `id` mediumint unsigned NOT NULL AUTO_INCREMENT,
  `title` varchar(200) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL,
  PRIMARY KEY (`id`)
) DEFAULT CHARSET=utf8;
INSERT INTO `publications` (`title`) 
VALUES
      ('Publication #1'),
      ('Publication #2'),
      ('Publication #3'),
      ('Publication #4'),
      ('Publication #5'),
      ('Publication #6');
      
CREATE TABLE `keywords_relation` (
  `id` int unsigned NOT NULL AUTO_INCREMENT,
  `keyword_id` mediumint unsigned DEFAULT NULL,
  `parent_id` mediumint unsigned DEFAULT NULL,
  `parent_type` tinyint unsigned DEFAULT NULL,
  PRIMARY KEY (`id`)
) DEFAULT CHARSET=utf8;
INSERT INTO `keywords_relation` (`keyword_id`,`parent_id`,`parent_type`) 
VALUES
      (1,1,0),
      (2,1,0),
      (4,1,0),
      (1,2,0),
      (4,2,0),
      (6,3,0),
      (6,4,0),
      (6,2,0),
      (2,1,0),
      (3,4,0),
      (3,5,4),
      (4,6,4),
      (4,2,4),
      (5,1,4),
      (5,3,4),
      (6,4,4),
      (6,6,4);
      #1,2,4

http://sqlfiddle.com/#!9/c1a035e/25

Problem

I want to retrieve all publications that belong to a certain research line, but the relationship is defined by common keywords. That's it, if a publication has one or more keywords in common with the research line, we say that the publication is part of that research line.

I need help tyding up the following relation.As of now it takes 3 different queries to retrieve the related publications and I bet it can be done in less & in a tidier way but I am completely lost.

Structure:

I have the following tables (simplified):

  • publications Research publications. columns id, title
  • lines Research Lines. columns id, title
  • keywords Keywords. columns id, name
  • keywords_relations A pivot table that contains many-to-many relationships between keywords, publications and research lines. columns id, keyword_id, parent_id, parent_type

Where keyword_relations.parent_id is 0 for research lines and 4 for publications.

Current approach

1.) Get the research line's keywords

1 in this case is the ID of a certain research line. As a result of this query I get an array of keyword ids.

select `keywords`.`id` from `keywords` 
inner join `keywords_relation` on `keywords`.`id` = `keywords_relation`.`keyword_id` 
where `keywords_relation`.`parent_id` = 1 and `keywords_relation`.`parent_type` = 0

2.) Get the ID's of publications that have those keywords

(?, ?, ?) would be the values retrieved from the previous query. in this case is the ID of a certain research line. As a result of this query I get an array of keyword ids.

select distinct `parent_id` from `keywords_relation` where `keyword_id` in (?, ?, ?) and `parent_type` = 4

3.) Get the publications

Using the result of the last ID, we feed the following query

select * from `publications` where `id` in (?, ?)

where (?, ?) is the list of publication IDs.

Request

Could someone help me tidy up this? Maybe in can be achieved in a single query using joins? I can not figure it out.

Please note that the relation between the lines and publications must be loose, that's it, via keywords.

P.s. I am using Laravel so every single of this tables represent a model (Keyword / Publication / Line) and a Pivot (KeywordActivity). In case someone wants to point out a laravel specific solution using eloquent.

Thanks!!!

Strawberry
  • 33,750
  • 13
  • 40
  • 57
Aquaguy
  • 357
  • 2
  • 11
  • @Strawberry Here you have it http://sqlfiddle.com/#!9/c1a035e/25 – Aquaguy Nov 03 '20 at 21:27
  • Didn't you just solve your problem by generating the fiddle-example? (The last query in it seems to be a working solution to your problem, e.g. one single query to give you your desired result). – Solarflare Nov 04 '20 at 00:03
  • @Solarflare yes, I know it's one query, but still it looks kind of ugly, can't this be achieved using joins? – Aquaguy Nov 04 '20 at 11:38

0 Answers0