Подзапрос в СОЕДИНЕНИИ

#sql #ms-access

#sql #ms-access

Вопрос:

Две таблицы в MS Access — клиенты и посещения — в продуктовой кладовой, где мы отслеживаем наших клиентов, когда они приходят и т.д.
Я хотел бы знать, какие клиенты раньше приходили, но в последнее время их не было; например, они пришли в pantry некоторое время в 2019 году, но с тех пор их не было.
Я получил приведенный ниже код от друга, который постоянно использует SQLPlus, но не знает Access.
Приведенный ниже код выдает мне «Синтаксическую ошибку при операции соединения». Спасибо за любую помощь в выполнении этого в Access.

 SELECT tbl_Clients.[First Name], tbl_Clients.[Last Name], tbl_Visits.[Session Date]
FROM tbl_Visits
INNER JOIN 
  (select tbl_Visits.[Client ID], Last(tbl_Visits.[Session Date]) as LastVisit 
     from tbl_Visits 
         group by tbl_Visits.[Session Date]) V1 
     ON (tbl_Visits.[Client ID] = tbl_Clients.[Client ID])
WHERE LastVisit between [Start date (mm/dd/yy)] and [End date (mm/dd/yy)];
  

Комментарии:

1. Это не сайт разработчиков кода… покажите нам все, что вы пробовали, и задайте конкретный вопрос. нет, пожалуйста, напишите это для меня…

Ответ №1:

Вы можете использовать агрегацию:

 select [Client ID], max([Session Date])
from tbl_visits
group by [Client ID]
having year(max([Session Date])) = 2019;
  

Если вам нужна дополнительная информация о клиентах, вы можете использовать это как подзапрос с INNER JOIN помощью , IN , или EXISTS .

Комментарии:

1. Спасибо за быстрый ответ. Это дало мне по сути то, что я хотел, и я изменил НЕОБХОДИМОСТЬ в соответствии со своими спецификациями.

Ответ №2:

Ваша непосредственная ошибка заключается в ссылке на таблицу, tblClients , в ON предложении, которое явно не объявлено в FROM or JOIN . Кроме того, вы не включаете подзапрос с псевдонимом, V1 , в ON предложение.

Кроме того, у вас есть недопустимый запрос агрегации, в котором вы GROUP BY указываете дату сеанса (сам агрегируемый столбец), но SELECT поле клиента. Вместо SELECT этого и GROUP BY поле client. Также лучше использовать MAX , а не LAST агрегат для дат.

В целом, рассмотрите приведенную ниже настройку, которая объединяет клиентов, посещения и подзапрос вместе, чтобы возвращать посещения каждого клиента, но только для тех клиентов, чье последнее посещение попадает в указанный диапазон времени. Затем результаты сортируются в порядке убывания по дате сеанса. Ниже используются более короткие псевдонимы таблиц.

 SELECT c.[First Name]
     , c.[Last Name]
     , v.[Session Date]
 
FROM (tbl_Clients c
INNER JOIN tbl_Visits v
  ON v.[Client ID] = c.[Client ID])

INNER JOIN 
    (SELECT sub_v.[Client ID]
           , MAX(sub_v.[Session Date]) AS LastVisit 
     FROM tbl_Visits sub_v
     GROUP BY sub_v.[Client ID]
    ) max_dt 
  ON c.[Client ID] = max_dt.[Client ID]

WHERE max_dt.LastVisit BETWEEN [Start date (mm/dd/yy)] 
                           AND [End date (mm/dd/yy)]

ORDER BY c.[First Name], v.[Session Date] DESC;
  

Если вам нужна агрегация только на уровне клиента, избегайте подзапроса и агрегируйте при объединении таблиц клиентов и посещений с HAVING фильтрацией на основе совокупного значения.

 SELECT  c.[First Name]
      , c.[Last Name]
      , MAX(v.[Session Date]) AS LastVisit 

FROM tbl_Visits v
INNER JOIN tbl_Clients c
   ON c.[Client ID] = v.[Client ID]
GROUP BY  c.[First Name]
        , c.[Last Name]
        , c.[Client ID]

HAVING MAX(v.[Session Date]) BETWEEN [Start date (mm/dd/yy)] 
                                 AND [End date (mm/dd/yy)];
  

Комментарии:

1. Ваш код выбирает каждую строку посещений, когда мне нужно только МАКСИМАЛЬНОЕ значение. Но спасибо за быстрый и элегантный ответ.