有5个表
books
------
id
name
year
author
------
id
name
store
------
id
name
books_authors
------
id
book_id
author_id
books_stores
------
id
store_id
book_id
每本书都可以有很多作者,每本书都可以在几家商店里。 我希望得到所有作者以及可以找到它的所有商店的书
我的代码(我使用PDO)
if(isset($_POST['books'])){
$books_ids = $_POST["books"];
}
$books_ids_in = implode(',', array_fill(0, count($books_ids), '?'));
$query = "SELECT b.id, b.name, b.year, a.name as author_name, s.name as store_name
FROM books as b
LEFT JOIN books_authors as b_a
ON b.id = b_a.book_id
LEFT JOIN authors as a
ON a.id = b_a.author_id
LEFT JOIN books_stores as b_s
ON b.id = b_a.book_id
LEFT JOIN stores as s
ON s.id = b_s.store_id
WHERE b.id IN (". $books_ids_in .")
ORDER BY b.id";
$stmt = $conn->prepare($query);
foreach ($books_ids as $k => $id) {
$stmt->bindValue(($k+1), $id);
}
$stmt->execute();
$results = $stmt->fetchAll();
但是在这种情况下,如果书有两个作者(例如)和每个商店的很多字符串,我会得到两个字符串。如何为所有作者和商店的每本书获得一个结果?
答案 0 :(得分:2)
您可以使用GROUP_CONCAT()
功能:
SELECT
b.id,
b.`name`,
b.`year`,
GROUP_CONCAT(DISTINCT a.`name`) AS author_names,
GROUP_CONCAT(DISTINCT s.`name`) AS store_names
FROM
books AS b
LEFT JOIN books_authors AS b_a ON b.id = b_a.book_id
LEFT JOIN authors AS a ON a.id = b_a.author_id
LEFT JOIN books_stores AS b_s ON b.id = b_a.book_id
LEFT JOIN stores AS s ON s.id = b_s.store_id
WHERE
b.id IN (". $books_ids_in .")
GROUP BY b.id
ORDER BY b.id
答案 1 :(得分:1)
PIL
操作的目的是产生组合爆炸。你额外的行是这种爆炸的结果。
每本书需要一行,显示作者和商店。这些行中的每一行都包含三种信息:书籍,作者,商店。因此,您需要可以为每种类型的信息每本书生成一个结果的子查询。然后你需要将这些子查询加在一起。
JOIN
很容易:你已经拥有一张每行一行的表。
对于books
,您需要这样:
authors
如果您知道某本书的作者应按ID顺序列出,请使用 SELECT ba.book_id, GROUP_CONCAT(a.name) author_names
FROM books_authors ba
LEFT JOIN authors a ON ba.author_id = a.id
GROUP BY ba.book_id
。顺便提一下,作者和作者自己认为作者的顺序非常重要。
该结果集包含
之类的行GROUP_CONCAT(a.author_name ORDER BY a.id)
你为商店做同样的事情。
17 James Watson, Francis Crick
19 Dewey, Cheatham, Howe
然后你将books表加入这两个子查询(a / k / a虚拟表),你就拥有了你想要的东西。
SELECT bs.book_id, GROUP_CONCAT(s.name) store_names
FROM books_stores bs
LEFT JOIN stores s a ON bs.store_id = s.id
GROUP BY bs.book_id
那会给你
SELECT b.id, b.name, aa.author_names, ss.store_names
FROM books b
LEFT JOIN (
SELECT ba.book_id, GROUP_CONCAT(a.name) author_names
FROM books_authors ba
LEFT JOIN authors a ON ba.author_id = a.id
GROUP BY ba.book_id
) aa ON b.id = aa.book_id
LEFT JOIN (
SELECT bs.book_id, GROUP_CONCAT(s.name) store_names
FROM books_stores bs
LEFT JOIN stores s a ON bs.store_id = s.id
GROUP BY bs.book_id
) ss ON b.id = ss.book_id