ADO 无法识别旧式 SQL 连接。不知道如何在此特定查询中使用新式语法
Posted
技术标签:
【中文标题】ADO 无法识别旧式 SQL 连接。不知道如何在此特定查询中使用新式语法【英文标题】:ADO not recognising old-style SQL joins. Don't know how to use new-style syntax in this particular query 【发布时间】:2020-01-08 14:20:14 【问题描述】:我正在使用 VBA 进行编码,使用 ADO 来查询与 Access 兼容 (JET) 的数据库。我有以下查询,效果很好:
SELECT
Answers.UserName AS UserName,
COUNT(Answers.Correct) AS CorrectAnswers
FROM
Answers
WHERE
Answers.QuizID=17
AND (SELECT COUNT(A.UserName) FROM Answers A WHERE A.QuizID=17 AND A.UserName=Answers.UserName)=30
GROUP BY Answers.UserName
这基本上是一个问答测验,其中每个答案都写入答案表。 Answers 表的一列是“UserName”,其中包含提交答案的用户的登录 ID。
但是,我想显示用户的全名,而不是登录 ID。这已经存储在一个单独的表“用户”中。在“用户”表中有两列:用户名和全名。
当然,显示全名的正确方法是使用如下连接:
SELECT
Users.FullName AS FullName,
COUNT(Answers.Correct) AS CorrectAnswers
FROM
Answers,
Users
WHERE
Answers.QuizID=17
AND (SELECT COUNT(A.UserName) FROM Answers A WHERE A.QuizID=17 AND A.UserName=Answers.UserName)=30
AND Users.UserName=Answers.UserName
GROUP BY Users.UserName
这也有效...只要用户名存在于用户表中。但是,如果出于某种原因,用户没有在 Users 表中注册,而不是返回 NULL,则不会完全选择记录。
在“旧式”连接语法中,我将通过在上述代码的相关行上添加一个 (+) 符号来解决这个问题,因此它显示为:
AND Users.UserName=Answers.UserName(+)
这将确保返回所有记录,即使用户表中不存在匹配项。然而,当我尝试这个时,ADO 会抛出一个错误:Extra ( in query expression... etc
。我推测这是因为 ADO 无法识别 (+) 语法。
所以问题是,是否有办法让 ADO 识别 (+) 连接;或者我应该如何以“新样式”连接语法编写查询以使其执行我想要的操作?
我的尝试:
SELECT
Users.FullName AS UserName,
COUNT(Answers.Correct) AS CorrectAnswers
FROM
Answers,
RIGHT JOIN Users U on Answers.Username = U.UserName
WHERE
Answers.QuizID=17
AND (SELECT COUNT(A.UserName) FROM Answers A WHERE A.QuizID=17 AND A.UserName=Answers.UserName)=30
GROUP BY Users.FullName
但这不起作用。它只是抛出Syntax Error
。我也试过Answers
后面不加逗号,没用。
有大量在线资源告诉人们如何使用新式联接。但是我没有看到任何东西告诉我如何正确地执行此操作,其中查询包括WHERE
中的其他子句。事实上,我发现所有新型连接示例都相对简单,它演示了如何在两个表上执行单个连接 - 查询没有其他元素。但是,当查询稍微复杂一点时,就不清楚应该如何使用语法了。
【问题讨论】:
去掉 RIGHT 前的逗号。除此之外,语法很好。 @jarlh 我已经尝试过了,如问题中所述。错误变为:No value given for one or more of the required parameters
.
这是另一个问题...
【参考方案1】:
您需要的是 Answers
到 Users
的 LEFT
连接,基于两个表中的 ON
列 UserName
。
这意味着即使Users
中没有匹配项,也会返回Answers
的所有行。
但是还有另一个问题:在SELECT
列表中,您有FullName
列,尽管您没有将其包含在GROUP BY
子句中,这是不允许的。
所以我也将它包含在GROUP BY
:
SELECT
a.UserName, u.FullName,
COUNT(a.Correct) AS CorrectAnswers
FROM Answers a LEFT JOIN Users u
ON u.UserName = a.UserName
WHERE a.QuizID=17
AND
(SELECT COUNT(aa.UserName) FROM Answers aa WHERE aa.QuizID = a.QuizID AND aa.UserName = a.UserName) = 30
GROUP BY a.UserName, u.FullName
虽然我不知道WHERE
子句中子查询的原因,但我相信它可以像这样在HAVING
子句中移动:
SELECT
a.UserName, u.FullName,
COUNT(a.Correct) AS CorrectAnswers
FROM Answers a LEFT JOIN Users u
ON u.UserName = a.UserName
WHERE a.QuizID=17
GROUP BY a.UserName, u.FullName
HAVING COUNT(*) = 30
【讨论】:
谢谢 - 这似乎工作!当然,下一步是在 SELECT 子句中用 UserName 代替 FullName,以防 FullName 为空。 NVL 似乎不起作用(我习惯于在 oracle 中工作)。 IsNull 也无法识别。我知道这是一个不同的问题,但你能建议吗? ;) 如果只需要 1 列,请将a.UserName, u.FullName
更改为 COALESCE(u.FullName, a.UserName)
使用 COALESCE 会导致错误:Method 'Open' of object '_Recordset' failed
。你确定 COALESCE 被 ADO 认可吗?
更新:COALESCE 不起作用,但 IIF(Condition, ValueIfTrue, ValueIfFalse) 起作用!谢谢。
如果您使用的是 MS Access,则 no coalesce() 不起作用。以上是关于ADO 无法识别旧式 SQL 连接。不知道如何在此特定查询中使用新式语法的主要内容,如果未能解决你的问题,请参考以下文章
如何在此 Access-SQL server-Visual Basic 6 (ADO) 表单中不包含重复元素(主详细信息)
delphi怎样在ADO里用ADOproc调用数据库sql server存储过程?,用ADODATASET或者ADOQUERY又怎样调用存储过程?