我是Access的新手,我有一个包含AuthorName
,BookTitle
和CoAuthor
的表格。 AuthorName
和BookTitle
是一个复合键。
目前查询提取的信息如下:
AuthorName---------BookTitle------CoAuthor
Steven King--------Dark Half------Peter Straub
Steven King--------Dark Half------John Doe
James Patterson----Another Time
Jeff Hanson--------Tales of Time---Joe Smith
我希望它(如果可能的话)动态阅读
AuthorName---------BookTitle---------CoAuthor1--------CoAuthor2
Steven King----------Dark Half--------Peter Straub-----Joe Doe
James Patterson----Another Time
Jeff Hanson----------Tales of Time----Joe Smith
因此,如果稍后添加了另一位作者,则会出现CoAuthor的第三列。
这可以用VBA还是SQL?
答案 0 :(得分:5)
你所要求的是反对使用关系数据库的全部意义;简而言之,您应该以最小化(而不是消除)重新设计表的需要的方式设计表。我建议你阅读database normalization。
事实上,你的问题是我在教授数据库时经常使用的一个例子: 你如何设计一个数据库来保存有关书籍和作者的所有信息 即可。场景是:
所以,这是一个多对多关系,并且有一种设计这样一个数据库的方法。
首先,为作者设计一个表格:
然后,为书籍设计一个表格:
最后,需要第三张表来描述作者和书籍:
(两个字段必须是主键的一部分)
现在,主要问题是:如何查询书籍及其作者?
假设上述设计,您可以编写SQL查询以获取书籍及其作者的完整列表:
select book_title, first_name, last_name
from
tbl_authors as a
inner join tbl_books_authors as ba on a.authorId = ba.authorId
inner join tbl_books as b on ba.bookId = b.bookId
这样,你就会有这样的事情:
book_title | first_name | last_name
-----------+------------+-----------
book1 | John | Doe
book1 | Jane | Doe
book2 | John | Doe
book2 | Peter | Who
book3 | Jane | Doe
book4 | Peter | Who
book5 | John | Doe
book5 | Jane | Doe
book5 | Peter | Who
book5 | Jack | Black
为什么这种设计比你原来的想法更好?
进一步阅读:
次要更新
这种设计将帮助您避免将来遇到很多麻烦,因为每次添加第三或第四作者时您都不需要更改表格。几年前我学习了数据库规范化,阅读" Running Access 97"作者:Jon Viescas(这不是商业广告,它只是一个参考文献;))...一本旧书,是的,但它对这个主题有很好的介绍。
现在,在规范化数据库之后,您可以使用数据透视查询来获取所需内容(如answer posted by Conrad Frix中所述)。
答案 1 :(得分:3)
如果您的表格类型如下
+-----------------+---------------+--------------+-----------+
| AuthorName | BookTitle | CoAuthor | Type |
+-----------------+---------------+--------------+-----------+
| Steven King | Dark Half | Peter Straub | CoAuthor1 |
| Steven King | Dark Half | John Doe | CoAuthor2 |
| James Patterson | Another Time | | CoAuthor1 |
| Jeff Hanson | Tales of Time | Joe Smith | CoAuthor1 |
+-----------------+---------------+--------------+-----------+
这将是一个非常简单的转换
TRANSFORM First(Books.CoAuthor) AS FirstOfCoAuthor
SELECT Books.AuthorName, Books.BookTitle
FROM Books
GROUP BY Books.AuthorName, Books.BookTitle
PIVOT Books.Type;
因为我们不需要动态创建它,首先为模拟ROW_NUMBER OVER的每一行分配一个数字,然后进行转换。在大型数据集上,这可能非常慢
TRANSFORM First(b.coauthor) AS firstofcoauthor
SELECT b.authorname,
b.booktitle
FROM (SELECT authorname,
booktitle,
coauthor,
'CoAuthor' & k AS Type
FROM (SELECT b.authorname,
b.booktitle,
b.coauthor,
Count(*) AS K
FROM books AS b
LEFT JOIN books AS b1
ON b.authorname = b1.authorname
WHERE [b].[coauthor] <= [b1].[coauthor]
OR (( ( b1.coauthor ) IS NULL ))
GROUP BY b.authorname,
b.booktitle,
b.coauthor) AS t) AS b
GROUP BY b.authorname,
b.booktitle
PIVOT b.type