Search code examples
mysqldatasetrowcreate-table

MySQL Query: Selecting rows of linked tables and catching a "bigger" dataset


I am trying to figure out how to build a query, which satisfies the following criteria.

I have two tables. Table a stores a list of authors. And table b stores a list of books. I have a linking table c, which maps every author to one ore more books. Naturally a book can have more then one author. Given a name (let's take name = "Douglas Adams") of an author, I know that if I do

SELECT * FROM linktable
    INNER JOIN a ON linktable.a_id = a.id
    INNER JOIN b ON linktable.p_id = b.id
WHERE a.name = 'Douglas Adams';

I get all the books which were written by Douglas Adams. Let us assume, Douglas Adams sometimes had "coauthors". How do I get them?

I want a list the somehow looks like this:

Douglas Adams, The Hitchhiker's Guide to the Galaxy, maybe more details...
Douglas Adams, Book_2, maybe more details...
Coauthor_1, Book_2, same Details as in "Douglas Adams, Book_2, maybe more details..."

Is this doable?


I have created 3 tables, which map what I want to store and what I want to retrieve.

The 2 storage tables are:

CREATE TABLE `a` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(100) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `name_UNIQUE` (`name`),
  KEY `name_INDEX` (`name`),
  FULLTEXT KEY `name_FULLTEXT` (`name`)
) ENGINE=MyISAM AUTO_INCREMENT=932723 DEFAULT CHARSET=utf8 COLLATE=utf8_bin

CREATE TABLE `b` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `title` varchar(1000) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL,
  PRIMARY KEY (`id`),
  FULLTEXT KEY `title_fulltext` (`title`)
) ENGINE=MyISAM AUTO_INCREMENT=1617432

and one third table, which links the 2 tables above.

CREATE TABLE `linktable` (
  `a_id` int(11) NOT NULL,
  `b_id` int(11) NOT NULL,
  KEY `a_id_INDEX` (`a_id`),
  KEY `b_id_INDEX` (`b_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci

Solution

  • SELECT a2.Name, b.title
        FROM a
            INNER JOIN linktable lt
                ON a.id = lt.a_id
            INNER JOIN b
                ON lt.b_id = b.id
            INNER JOIN linktable lt2
                ON lt.b_id = lt2.b_id
            INNER JOIN a a2
                ON lt2.a_id = a2.id
        WHERE a.Name = 'Douglas Adams'
        ORDER BY b.title,
                 /* Case Statement so Douglas Adams sorts before other authors */
                 CASE WHEN a2.Name = 'Douglas Adams' THEN 1 ELSE 2 END,
                 a2.Name