ADO не распознает присоединения в старом стиле SQL. Не знаю, как использовать синтаксис нового стиля в этом конкретном запросе - PullRequest
0 голосов
/ 08 января 2020

Я пишу в 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

Это в основном тест Q & A, в котором каждый ответ записывается в таблицу ответов. Один столбец таблицы «Ответы» - это «Имя пользователя», в котором содержится идентификатор входа пользователя, отправившего ответ.

Однако вместо идентификатора входа я хочу отобразить полное имя пользователя. Это уже хранится в отдельной таблице «Пользователи». В таблице «Пользователи» есть два столбца: UserName и FullName.

Естественно, правильный способ отображения полного имени будет с объединением следующим образом:

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. Однако, если по какой-либо причине пользователь не зарегистрирован в таблице Users, вместо возврата NULL, запись не будет выделена полностью.

В синтаксисе соединения "старого стиля" я решил бы это, добавив (+) символ на соответствующей строке в приведенном выше коде, поэтому он гласит:

AND Users.UserName=Answers.UserName(+)

Это обеспечит возвращение всех записей, даже если совпадения не существует в таблице Users. Однако, когда я пытаюсь это сделать, 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. Действительно, я обнаружил, что все примеры соединений в новом стиле относительно просты c, где продемонстрировано, как выполнить одно соединение для двух таблиц, где нет других элементов в запросе. Однако, когда запрос даже немного сложнее, неясно, как использовать синтаксис.

1 Ответ

2 голосов
/ 08 января 2020

Вам необходимо объединить LEFT из Answers в Users на основе ON столбцов UserName в обеих таблицах. Это означает, что будут возвращены все строки Answers, даже если в Users нет совпадений. Но есть и другая проблема: в списке 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
...