1

Suppose I have the following schema, and for your information, I'm using MySQL:

Paper(paperId, title) Author(authorId, authorName) Paper_Author(paperId, authorId)

I design the tables like this because a Paper may have more than one Author and a Author may write more than one Paper.

I'd now like to get the title and all the authors of a Paper.

I've been wondering if I could do this in one single statement?

If it is a YES, then how? So far I have only come with an idea of trying to get an array of Authors right from MySQL.

If it is a NO, how can I do it to maintain the atomicity of the transaction? (Let's consider getting the title and the author as ONE transaction)

Edit - in response to Justin E's comment:

I'd like to get something like this:

array(
    "title" => "ABC"
    "authors" => array("Ken", "Kitty", "Keith")
)
2
  • This would be difficult to achieve when there are multiple books in your result set. The answer I provided allows for you to get the name of the book in a simple foreach loop, with an array of authors. Commented Dec 7, 2015 at 16:18
  • Would answer from @Blag works then? Commented Dec 7, 2015 at 16:25

2 Answers 2

3

MySQL GROUP_CONCAT() is what you need (and maybe PHP explode())

SQL Fiddle

MySQL 5.5 Schema Setup:

CREATE TABLE Paper (`paperId` int, `title` varchar(7));
INSERT INTO Paper (`paperId`, `title`)
VALUES (1, 'hello'),(2, 'hola'),(3, 'bonjour');

CREATE TABLE Author (`authorId` int, `authorName` varchar(3));
INSERT INTO Author (`authorId`, `authorName`)
VALUES (1, 'me'),(2, 'moi');

CREATE TABLE Paper_Author (`paperId` int, `authorId` int);
INSERT INTO Paper_Author (`paperId`, `authorId`)
VALUES (1, 1),(1, 2),(2, 2);

Query 1:

SELECT Paper.`title`, GROUP_CONCAT(Author.`authorName`) as `authors`
FROM Paper_Author
INNER JOIN Paper
  ON Paper.`paperId` = Paper_Author.`paperId`
INNER JOIN Author
  ON Author.`authorId` = Paper_Author.`authorId`
GROUP BY Paper.`title`

Results:

| title | authors |
|-------|---------|
| hello |  me,moi |
|  hola |     moi |
Sign up to request clarification or add additional context in comments.

3 Comments

What will I get? Is it sth like this? title: "ABC", author: {"Ken", "Kitty"}
@ChungLunYuen yes, you get a list separated by , : Ken,Kittyor what you pass as 2param
Oh! That's exactly what I need! Thank you! ^^
2
SELECT paper.*, author.* FROM paper_author 
  LEFT JOIN paper USING(paperid)
  LEFT JOIN author USING(authorid)

Your array will look like:

Array(
  0 => Array(
    'title' => 'This is a title',
    'authorname' => 'This is an Authors Name',
  )
);

$authors = array();
while($row = $stmt->fetch(PDO::FETCH_ASSOC)){
    $authors[$row['title']][] = $row['authorname'];
}

print_r($authors);

Array(
    'Book 1' => array(
         'John Smith',
         'Jane Doe'
    )
);

2 Comments

Example updated with PDO code that would make an array keyed by book name with multiple child elements for each title representing an author.
I have also edited my question to specify what I need.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.