从行Access 2010动态创建列

时间:2014-07-02 20:59:21

标签: sql vba ms-access access-vba

我是Access的新手,我有一个包含AuthorNameBookTitleCoAuthor的表格。 AuthorNameBookTitle是一个复合键。

目前查询提取的信息如下:

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?

2 个答案:

答案 0 :(得分:5)

你所要求的是反对使用关系数据库的全部意义;简而言之,您应该以最小化(而不是消除)重新设计表的需要的方式设计表。我建议你阅读database normalization

事实上,你的问题是我在教授数据库时经常使用的一个例子: 你如何设计一个数据库来保存有关书籍和作者的所有信息 即可。场景是:

  • 一本书可以有一位或多位作者
  • 作者可能已经写过一本或多本书

所以,这是一个多对多关系,并且有一种设计这样一个数据库的方法。

首先,为作者设计一个表格:

  • tbl_authors
    • author_idd(主键,数字,首选自动数字)
    • first_name(String)
    • last_name(String)

然后,为书籍设计一个表格:

  • tbl_books
    • book_id(主键,数字,首选自动数字)
    • book_title(String)

最后,需要第三张表来描述作者和书籍:

  • tbl_books_authors
    • book_id(主键,数字)
    • author_id(主键,数字)
    • main_author(布尔值:"是"如果是主要作者,"否"否则)

(两个字段必须是主键的一部分)

现在,主要问题是:如何查询书籍及其作者?

假设上述设计,您可以编写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

为什么这种设计比你原来的想法更好?

  • 因为您不需要更改表格的结构以添加其他作者
  • 因为你不知道先验一本书可以有多少作者
  • 因为您在数据库中避免了冗余
  • 因为通过这种设计,您将能够使用前端工具(如Access表单和报表或其他工具)来创建几乎任何来自此数据的工具。

进一步阅读:


次要更新

这种设计将帮助您避免将来遇到很多麻烦,因为每次添加第三或第四作者时您都不需要更改表格。几年前我学习了数据库规范化,阅读" 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