我的数据库中有一本书(60,000本书)和作者(37,000位作者)。一本书可能由多位作者撰写。因此,book表在book表的author_id列中使用逗号分隔的author_ids 书表
book_master_id book_name author_id
1 Book 1 22,23
2 Book 2 23
3 Book 3 24
4 Book 4 23,24
作者表
author_id author_name
22 Jim
23 Roger
24 Andrew
现在,如果我想将结果作为作者姓名,并按书写计数的降序排列。即
Roger(3)
Andrew(2)
Jim(1)
什么应该是Mysql查询?请告诉我步骤。 还要将执行时间视为最小值 谢谢
答案 0 :(得分:5)
您应该规范化数据库表,正如其他几个人已经提到的那样。结果数据库结构应如下所示:
BOOK_MASTER
book_master_id book_name
1 Book 1
2 Book 2
3 Book 3
4 Book 4
AUTHOR
author_id author_name
22 Jim
23 Roger
24 Andrew
BOOK_AUTHOR
book_master_id author_id
1 22
1 23
2 23
3 24
4 23
4 24
您应该在数据库架构上设置正确的约束,但这会给您一个想法。
使用此数据库结构,您可以使用以下查询来获得所需的结果:
SELECT
a.author_name,
COUNT(*) as number_of_books
FROM
author a
JOIN book_author ba ON a.id = ba.author_id
GROUP BY
a.author_name
ORDER BY number_of_books DESC
编写一个脚本,将当前书籍表的author_id逗号分隔列表移动到新的author_book表中应该是相当简单的,下面的内容可能会起作用:
<?php
$query = "SELECT book_master_id, author_id FROM books";
$result = mysql_query($query);
while ($row = mysql_fetch_row($result)) {
$values = array();
foreach (explode(',', $row['author_id']) as $authorId) {
$values[] = "(" . $row['book_master_id'] . ", " . $authorId . ")";
}
$query = "INSERT IGNORE INTO book_author (book_master_id, author_id) VALUES ";
$query .= implode(', ', $values);
mysql_query($query);
}
请注意,我没有测试此代码,您应该首先在测试数据库上进行测试,看看它是否确实执行了它应该执行的操作。此外,如果您有大量数据,则此脚本可能需要一些时间才能执行。最后,也许有一个SQL查询可以做到这一点,但这是第一个想到的解决方案。
答案 1 :(得分:1)
如果你真的想要最少的执行时间,我想你也想拥有一个好的表结构。你的逗号分隔列表绝对不是。 您应该添加第三个表,它将book表和authors表链接在一起。 它可能是这样的:
book_master_id author_id
1 22
1 23
2 23
3 24
4 23
4 24
通过这种方式,您可以轻松计算每位作者的书籍,并执行许多其他不合理复杂的查询,否则会很慢。
答案 2 :(得分:1)
正如ypercube指出的那样,逗号分隔的ID字符串值非常糟糕,无论如何都会破坏你的性能...... Jan-Henk指出了一个正确的结构来处理以及查询......但是,如果你不能改变结构(强烈推荐),你必须延长Sashi的产品。
如果在逗号分隔列表中查找“喜欢”比较,则会出现与
等数字冲突作者ID在“123,223,323,423,1235,36235”的作者串中找到,但他们都不是作者23.您必须在开头和结尾用逗号包装您的作者以确保您看起来很明显“ ,23,“被发现在字符串中。
select auther_name,count(*)
from authors au
inner join books bo
on concat( ",", au.author_id, "," ))
like CONCAT('%,', bo.authors,',%')
group by author_name order by count(*) desc;
答案 3 :(得分:0)
select auther_name,count(*)
from authors au
left join books bo
on au.author_id like CONCAT('%', bo.author_id,'%')
group by author_name order by count(*) desc;
答案 4 :(得分:0)
SELECT author_name + ' ( '+
cast((
select count(author_id) from book
where author_id like '%'+cast(author.author_id as varchar(10))+'%')as nvarchar(50) ) +')'
FROM author
它在ms sql server 2005中工作,所以你可以改变是否需要mysql