OLTP-数据库设计

时间:2014-04-24 16:33:08

标签: database

我需要帮助。我有2个表和书籍作者

  • 一本书可以有多个作者
  • 一位作者可以写多本书

所以我设计了Mapping / Junction表来维持这种关系

我的要求 - 我想获得给定作者组合的书籍ID,名称。 比如下面的例子Book' B3' (103)作者A2& A3。所以我的输入将是302& 303(A2& A3 id' s)和查询应该给我103(书ID)

如果需要,

建议架构更改

以下是SQL Server 2005及更高版本中的示例代码工作

declare @tbl_Books TABLE (Book_ID INT, Book_Name VARCHAR(500))
declare @tbl_Authors TABLE (Author_ID INT, Author_Name VARCHAR(50))
declare @tbl_Mapping TABLE (Mapping_ID INT IDENTITY(1,1), Book_ID INT, Author_ID INT)

insert into @tbl_Books VALUES (101,'B1'),(102,'B2'),(103,'B3')
insert into @tbl_Authors VALUES (301,'A1'),(302,'A2'),(303,'A3')
insert into @tbl_Mapping VALUES (101,301),(101,302),(102,301),(102,302),(101,303),(103,302),(103,303)

select * from @tbl_Books
select * from @tbl_Authors
select * from @tbl_Mapping

Table : tbl_Books
==========   
Book_ID Book_Name
101 B1
102 B2
103 B3

Table: tbl_Authors   
===================
Author_ID   Author_name
301 A1
302 A2
303 A3

Table:tbl_Mapping        
==============
Mapping_ID  Book_ID Author_ID
1   101 301
2   101 302
3   102 301
4   102 302
5   102 303
6   103 302
7   103 303

2 个答案:

答案 0 :(得分:1)

这不太好但是有效:

SELECT x.book_id, b.book_name 
FROM (SELECT book_id, COUNT(*) AS num FROM tbl_mapping GROUP BY book_id) x  --Get all books with a count of their authors
INNER JOIN (SELECT book_id FROM tbl_mapping WHERE author_id IN (302,303)) y  --Get all books which involve the specified authors
    ON y.book_id = x.book_id
INNER JOIN tbl_books b
    ON b.book_id = x.book_id
WHERE x.num = 2  --Filter for books which have exactly the required number of authors
GROUP BY x.book_id, b.book_name 
HAVING COUNT(*) = 2  --Filter for how many times each book appears in the results. We want those that appear as many times as there are authors being searched

为了减少静态,您必须根据您提供的作者ID列表以及IN所需的内容来构建= 2子句,以便更改2 1}}到被搜索的作者数量。

我通过在仅由一位作者编写的示例数据中添加另一本书并相应地调整查询来测试它。它回归了我的预期。还试过这本书和三位作者一起工作。这几乎不构成强大的测试,但它证明了基本概念。我确定有一个更好的方法可以使用窗口功能,但坦率地说,这是我的晚餐时间,我正在挨饿,所以我想不到它!

答案 1 :(得分:0)

因此,您正在寻找给定作者集的书籍ID和书名。

你可以尝试类似(非常多的伪sql):

select tb.Book_ID, tb.Book_Name, SUM(tm.Author_ID) as authors FROM tbl_Mapping tm
       INNER JOIN tbl_Book tb on tb.Book_ID = tm.Book_ID
       WHERE tm.Author_ID IN ( <your list of authors>)
       AND authors = (<the number of authors passed in>)
       GROUP BY tb.Book_ID

但是我不确定作者别名作为过滤器的合法性(我从来没有在SQL中真正做过这个直接)

然而,编程方法是查询:

select Book_ID from tbl_Mapping WHERE Author_ID = <One author ID>

把它放在一个循环中。上面的查询是第一次执行,后来的查询也有

AND BOOK_ID IN (<List of Book IDs returned by previous loops)

你循环直到你的作者用完为止,然后通过查询运行这些ID来获取名称(或者你将名字添加到之前的查询中并跟踪它)。