MS Access SQL: проблемы, объединяющие UNION ALL и LEFT JOIN - PullRequest
0 голосов
/ 21 декабря 2010

Я создал запрос в MS Access, чтобы смоделировать FULL OUTER JOIN и объединить результаты, которые выглядят примерно так:

SELECT NZ(estimates.employee_id, actuals.employee_id) AS employee_id
, NZ(estimates.a_date, actuals.a_date) AS a_date
, estimates.estimated_hours
, actuals.actual_hours
FROM (SELECT *
      FROM estimates
      LEFT JOIN actuals ON estimates.employee_id = actuals.employee_id
         AND estimates.a_date = actuals.a_date
      UNION ALL
      SELECT *
      FROM estimates
      RIGHT JOIN actuals ON estimates.employee_id = actuals.employee_id
         AND estimates.a_date = actuals.a_date
      WHERE estimates.employee_id IS NULL
         OR estimates.a_date IS NULL) AS qFullJoinEstimatesActuals

Я сохранил этот запрос как объект (назовем его qEstimatesAndActuals). Моя цель - ПОДКЛЮЧИТЬ qEstimatesAndActuals к другой таблице. Примерно так:

SELECT *
FROM qJoinedTable
LEFT JOIN (SELECT *
           FROM labor_rates) AS rates
ON qJoinedTable.employee_id = rates.employee_id
   AND qJoinedTable.a_date BETWEEN rates.begin_date AND rates.end_date

MS Access принимает синтаксис и выполняет запрос, но пропускает результаты, которые явно находятся в наборе результатов. Удивляясь, что формат даты был каким-то образом потерян, я поместил FORMAT вокруг begin_date и end_date, чтобы заставить их интерпретироваться как Short Dates. Как ни странно, это привело к другому набору результатов, но все равно пропустил результат, которого не должно было быть.

Мне интересно, если запросы выполняются таким образом, что вы не можете присоединиться к результирующему набору UNION ALL. У кого-нибудь есть мысли / идеи по этому поводу? Есть ли лучший способ достижения конечной цели?

Ответы [ 3 ]

1 голос
/ 21 декабря 2010

Я бы попытался разбить каждую часть запроса на отдельный объект запроса доступа, например,

SELECT *
  FROM estimates
  LEFT JOIN actuals ON estimates.employee_id = actuals.employee_id
     AND estimates.a_date = actuals.a_date

Было бы qryOne

SELECT *
  FROM estimates
  RIGHT JOIN actuals ON estimates.employee_id = actuals.employee_id
     AND estimates.a_date = actuals.a_date
  WHERE estimates.employee_id IS NULL
     OR estimates.a_date IS NULL

Было бы qryTwo

SELECT * FROM qryOne
UNION ALL
SELECT * FROM qryTwo

Было бы qryFullJoinEstimatesActuals и, наконец,

SELECT NZ(estimates.employee_id, actuals.employee_id) AS employee_id
, NZ(estimates.a_date, actuals.a_date) AS a_date
, estimates.estimated_hours
, actuals.actual_hours
FROM qryFullJoinEstimatesActuals

Я обнаружил, что конструкции, которые не работают в сложных SQL-выражениях Access, часто работают правильно, если они разбиты на отдельные объекты запроса и повторно собраныий шаг.Кроме того, вы можете проверить каждую часть запроса в отдельности.Это поможет вам найти обходной путь, если окажется необходимым.

0 голосов
/ 21 декабря 2010

В соответствии со странным поведением, связанным с датами, эта проблема оказалась связанной с использованием NZ для выбора даты в qFullJoinEstimatesActuals. Использование NZ делает тип данных неоднозначным. Таким образом, следующая строка из примера в моем сообщении вызвала ошибку:

, NZ(estimates.a_date, actuals.a_date) AS a_date

Неоднозначный тип данных a_date привел к тому, что оператор BETWEEN выдал ошибочные результаты при сравнении a_date с rate.begin_date и Rate.end_date в LEFT JOIN. Проблема была решена путем приведения типа результата функции NZ следующим образом:

, CDate(NZ(estimates.a_date, actuals.a_date)) AS a_date
0 голосов
/ 21 декабря 2010

Вы можете найти, как именно это сделать здесь .

Вам не хватает INNER JOIN .... UNION ALL step.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...