Sql 从Access 2010的行动态创建列

Sql 从Access 2010的行动态创建列,sql,ms-access,vba,Sql,Ms Access,Vba,我是一个比较新的访问对象,我有一个包含AuthorName、BookTitle和CoAuthor的表。AuthorName和BookTitle是一个复合键 当前,查询提取的信息如下: AuthorName---------BookTitle------CoAuthor Steven King--------Dark Half------Peter Straub Steven King--------Dark Half------John Doe James Patterson----Ano

我是一个比较新的访问对象,我有一个包含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
所以,如果后来添加了另一位作者,则会出现第三列“合著者”


这在VBA或SQL中是可能的吗?

您所要求的与使用关系数据库的整个要点背道而驰;简言之,您应该以最小化而不是消除重新设计表的需要的方式来设计表。我建议你读一下

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

一本书可以有一个或多个作者 作者可能写过一本或多本书 这是一种多对多关系,有一种方法可以设计这样的数据库

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

tbl_作者 作者ID主键,数字,最好是自动数字 名字字符串 姓氏字符串 然后,为书籍设计一个表格:

tbl_书籍 图书id主键,数字,最好是自动数字 书名字符串 最后,需要第三个表格来关联作者和书籍:

tbl\u书籍\u作者 图书id主键,数字 作者id主键,数字 主作者布尔值:如果是主作者,则为“是”,否则为“否” 这两个字段都必须是主键的一部分

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

根据上述设计,您可以编写一个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窗体和报表之类的前端工具,或其他工具来从这些数据创建几乎任何阵列。 进一步阅读:

特地 小更新

这种设计将帮助您避免将来的许多麻烦,因为您不必每次添加第三或第四作者时都更改表。几年前,我在阅读Jon Viescas的《运行Access 97》时了解了数据库规范化。这不是一个商业广告,只是一个参考。。。是的,这是一本旧书,但它对这个主题有很好的介绍


现在,在规范化了数据库之后,您可以使用pivot查询来获取所需内容,如中所述。

您所要求的内容与使用关系数据库的整个要点背道而驰;简言之,您应该以最小化而不是消除重新设计表的需要的方式来设计表。我建议你读一下

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

一本书可以有一个或多个作者 作者可能写过一本或多本书 这是一种多对多关系,有一种方法可以设计这样的数据库

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

tbl_作者 作者ID主键,数字,最好是自动数字 名字字符串 姓氏字符串 然后,为书籍设计一个表格:

tbl_书籍 图书id主键,数字,最好是自动数字 书名字符串 最后,需要第三个表格来关联作者和书籍:

tbl\u书籍\u作者 图书id主键,数字 作者id主键,数字 主作者布尔值:如果是主作者,则为“是”,否则为“否” 这两个字段都必须是主键的一部分

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

根据上述设计,您可以编写一个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窗体和报表之类的前端工具,或其他工具来从这些数据创建几乎任何阵列。 进一步阅读:

特地 小更新

这种设计将帮助您避免将来的许多麻烦,因为您不必每次添加第三或第四作者时都更改表。几年前,我在阅读Jon Viescas的《运行Access 97》时了解了数据库规范化。这不是一个商业广告,只是一个参考。。。 是的,这是一本旧书,但它对这个主题有很好的介绍


现在,在规范化数据库之后,如果表的类型如下所示,则可以使用pivot查询来获取所需内容。

+-----------------+---------------+--------------+-----------+
|   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;
因为它不存在,所以我们需要动态地创建它,首先为每行分配一个数字,然后进行转换。在大型数据集上,这可能相当缓慢

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 

如果您的表格有如下类型

+-----------------+---------------+--------------+-----------+
|   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;
因为它不存在,所以我们需要动态地创建它,首先为每行分配一个数字,然后进行转换。在大型数据集上,这可能相当缓慢

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 

具体来说,使用这样的结构,可以使用Access交叉表查询来获取您可能要查找的输出。+1表示整个消息,但[mainAuthor]的用途尚不清楚。将其放在[tbl_authors]表中意味着给定的作者将是其参与的每一项工作的主要作者。如果两位主要作者在同一本书上工作,这意味着什么?我的直觉告诉我,[main author]应该在[tbl_books_authors]表中。@barrank是一个很好的总结,但为什么要在camelCase和snake_case之间切换呢?OP用PascalCase把它框起来。无论选择什么,我都不会在一个应用程序中混合使用多个约定。@JeremyCook也许这只是在某些主题上自学的问题。。。我只是觉得在snake_案例中命名表和在camelCase中命名字段很舒服。。。但是是的,你是对的,我违反了。。。correcting@JeremyCook不需要重新设计就可以进行交叉表查询。具体来说,在这样的结构中,可以使用Access交叉表查询来获取您可能需要的输出。+1表示整个消息,但[mainAuthor]的用途尚不清楚。将其放在[tbl_authors]表中意味着给定的作者将是其参与的每一项工作的主要作者。如果两位主要作者在同一本书上工作,这意味着什么?我的直觉告诉我,[main author]应该在[tbl_books_authors]表中。@barrank是一个很好的总结,但为什么要在camelCase和snake_case之间切换呢?OP用PascalCase把它框起来。无论选择什么,我都不会在一个应用程序中混合使用多个约定。@JeremyCook也许这只是在某些主题上自学的问题。。。我只是觉得在snake_案例中命名表和在camelCase中命名字段很舒服。。。但是是的,你是对的,我违反了。。。correcting@JeremyCook不需要重新设计就可以进行交叉选项卡。以下是答案:-另一个答案是对初学者有用的信息和对经验丰富者的提醒。感谢您提供有关如何完成任务的信息和示例。我不会想到使用交叉表查询来完成这项工作。感谢所有提供意见的人。@user3799282如果此答复回答回答了您的问题,请单击answar左侧的v将其标记为answar。它将变成绿色v,并为所有SO用户标记您的Q。谢谢这是答案:-另一个答案是对初学者有用的信息和对有经验者的提醒。谢谢你提供的信息和如何完成任务的好例子。我不会想到使用交叉表查询来完成这项工作。感谢所有提供意见的人。@user3799282如果此答复回答回答了您的问题,请单击answar左侧的v将其标记为answar。它将变成绿色v,并为所有SO用户标记您的Q。谢谢