返回多个字段的 MS Access 子查询

Posted

技术标签:

【中文标题】返回多个字段的 MS Access 子查询【英文标题】:MS Access Subquery that returns Multiple Fields 【发布时间】:2013-03-08 21:01:31 【问题描述】:

所以我又回来了,遇到了更多的 MS Access 问题。我有一个带有子查询的 INSERT INTO 查询,用于检查数据是否已经存在。

SELECT name, course
FROM foo    
WHERE (name, course) NOT IN (SELECT name, course FROM bar);

解释一下我想要完成的事情,因为上述方法不起作用。

我正在尝试选择表格栏中尚不存在的复合键。例如,可以在表格栏中存储以下内容:

"John Doe" , "Calc 101" 
"John Doe" , "English"
"Jane Doe" , "Calc 101"

以下可能在表 foo 中:

"John Doe", "Calc 101"
"John Doe", "Science"

查询应返回以下内容:

"John Doe", "Science"

我看过的所有地方都说上面的方法会起作用,我相信它在理论上是有效的。我遇到的问题是 MS Access... 当我尝试运行此查询时,它会弹出说明子查询将返回多个字段。事实上,它应该是我想要它做的就是返回 2 个字段,我可以比较其他 2 个字段。以上 2 个字段是我的“bar”数据库中的复合键。

有关更多背景信息,我正在使用 MS Excel 2007 和 MS Access 2007。Excel 用于输入数据并通过 VB 脚本运行查询。我正在尝试创建一个子查询来检查最终数据库中已经存在的字段,因为我遇到了打开 MS Access 的错误,并吐出一条关于附加主键的错误消息,并在不执行查询的情况下关闭。

【问题讨论】:

你说“我看过的所有地方都说上面的方法可以工作......”你能展示你的来源吗? 【参考方案1】:

使用LEFT JOIN 并查找NULL 值:

SELECT bar.name, bar.course
FROM bar LEFT JOIN foo ON bar.name = foo.name AND bar.course = foo.course
WHERE foo.name IS NULL

我更新了SQLFiddle 以包含INSERT,后跟SELECT 以显示决赛桌。我还在两个表中添加了复合主键,因此您可以看到没有任何重复的插入。

【讨论】:

谢谢托尼。我认为这是我需要的,而您构建的 SQLFiddle 帮助我更好地理解了它。我会多玩一点以确保但我相信它会起作用^_^ 所以在玩了一会儿 SQLfiddle 之后,我有一个后续问题。我注意到如果我尝试在查询上方添加一个 INSERT INTO 子句。 (我这样做是假设我可以将返回的记录附加到表中)SQL Fiddle 返回零记录。可能是我不懂 SQLFiddle,但我目前不在办公室测试我在访问环境中的发现 @JohnathonHall - 我已经更新了 SQL Fiddle 以执行 INSERT 谢谢,我只是没有在插入之后放置 Select 查询。只是我不知道如何使用 SQL Fiddle。再次感谢。 ^_^【参考方案2】:

您的子查询返回两列。让它返回一个。如果想要一个可以在两列中的 where 子句,请使用 OR

SELECT name, course
FROM foo    
WHERE (name) NOT IN (SELECT name FROM bar) and (course) 
NOT IN (SELECT course FROM bar);

编辑:

您的问题源于规范化问题。建议的重新设计是为学生提供一张桌子,为课程提供一张桌子,并为他们提供一张桌子。示例:

**StudentTable**
studentId(int PK)
firtName(string)
lastName(string)

**ClassTable**
classId(int PK)
ClassName
ClassDesc

**classTable_studentTable**
studentClassID
studentID
classID

每个学生可以有很多班级,每个班级可以有很多学生。这是一个多对多关系,通过使用连接表进行规范化。

现在,如果你想做一个像你问的那样的查询:

Select *.student, *.class
from
studentTable as student,
classTable as class
where
student.name<>'allen' and class.name<>'math' 

【讨论】:

所以我想我没有听懂你所说的。我想了解与只是复制粘贴并就像是的那样有效。但是现在使用 Where 子句基本上是 2 个子查询。这会返回复合值吗? 从逻辑上讲,我们的两个子查询都在说同样的事情。我只是拆分了 where 子句。我不是说 ('col1','col2') 中的 WHERE 值,而是说 'col1' 中的值和 'col2 中的值。不过,正如旁注一样,您遇到困难的原因是因为您的表格没有标准化。您的表中不应包含冗余数据(例如,多个 Johnathan Hall 的数据。我将编辑我的回复以表明您必须对其进行规范化 @jason - 如果主键是名称和课程的组合,则原始表被规范化。您添加代理键无济于事;事实上,如果您的 classTable_studentTable 主键是 studentClassID,那么您最终可能会得到多行学生上同一堂课。 这就是为什么我将 studentClassID 添加为 PK 并且没有使用复合键,因为您可以让同一个学生参加相同的课程。除非您引入学期表来区分同一学生何时修读同一门课程。此外,您的示例表未标准化,因为如果您必须更改学生的姓氏或课程名称,您将遇到各种更新/删除异常 OP 没有提到任何关于重复行的内容,实际上该表上已经有一个复合键。该问题没有说明“......您可以让同一个学生参加相同的课程。”如果更新查询(例如 UPDATE table SET name = 'Jane Smith' WHERE name = 'Jane Doe')是 Student 表中的主键,它会如何导致异常?【参考方案3】:

查询:

SELECT name, course
FROM foo    
WHERE (name, course) NOT IN (SELECT name, course FROM bar);

适用于 mysql 和 Oracle。对于 Access,这也适用于 MySQL 和 Oracle,您可以将其重写为:

SELECT name, course
FROM foo    
WHERE name NOT IN (SELECT name FROM bar)
AND course NOT IN (SELECT course FROM bar);

【讨论】:

以上是关于返回多个字段的 MS Access 子查询的主要内容,如果未能解决你的问题,请参考以下文章

使用包含 SUM() 字段的子查询在 MS-Access 中编辑查询

基于包含子查询的查询的 ms-access 交叉表查询

子窗体内的 MS Access 参数查询不会打印

带有子查询的 SQL 查询上的 MS Access VBA 运行时错误 3075

MS-Access SELECT TOP N 子查询 SQL

在 MS Access 中以分号分隔的列表检索电子邮件地址的子查询