Запрос Access с несколькими таблицами возвращает пробелы для одной таблицы

#sql #ms-access #join

#sql #ms-access #Присоединиться

Вопрос:

У меня нет опыта программирования или базы данных (кроме как в качестве конечного пользователя), и я создаю базу данных с доступом в 365. У меня очень ограниченное представление о SQL.

Я написал запрос с несколькими таблицами для создания отчета, и он в основном работает. Он вернет все запрошенные данные для всех таблиц, кроме одной (CostumeInventory) . Для этой таблицы он создает столбцы (ItemName, Description, Condition, RentalRate, ReplacementValue) , но строки в этих столбцах пустые. Скриншот. В таблице CostumeInventory они обязательны, имеют значение short text, и все они содержат данные.

При разработке запроса, если я щелкну по соединению с CostumeInventory, у меня будет выбран вариант 3. Скриншот21 ничего не возвращает, а 2 сообщает мне исправить ошибку «неоднозначное внешнее соединение» при попытке ее запуска. Я попытался создать подзапросы двумя разными способами (один объединяет RentalInvenory и CostumeInventory, а другой объединяет все таблицы Rental- tables с CostumeInventory), и ни один из них не дал никаких результатов. Какие-либо предложения, которые я могу попробовать? Заранее благодарю вас! Ниже приведен код, написанный Access:

 SELECT RentalClients.CompanyName, RentalDetails.ShowTitle, RentalDetails.Designer,
    RentalDetails.OpeningDate, RentalDetails.ClosingDate, RentalDetails.FirstFitArrivalDate,
    RentalDetails.ApprovalDate, RentalDetails.ReturnDate, RentalClients.CostumeContact,
    RentalClients.CostumeEmail,
    RentalInventory.InventoryID, CostumeInventory.ItemName, CostumeInventory.Description,
    CostumeInventory.Condition, CostumeInventory.RentalRate, CostumeInventory.ReplacementValue
FROM (RentalClients
  INNER JOIN RentalDetails ON RentalClients.ClientID = RentalDetails.ClientID) 
  INNER JOIN (CostumeInventory
    RIGHT JOIN RentalInventory
    ON CostumeInventory.InventoryRecordID = RentalInventory.InventoryID)
  ON RentalDetails.RentalID = RentalInventory.RentalID
WHERE (((RentalDetails.RentalID)=[forms]![frmUpdateRental]![cboSelectRental]) AND
  ((RentalInventory.ReturnedApproval)=False) AND
  ((RentalInventory.ReturnedOpening)=False) AND
  ((RentalInventory.ReturnedFinal)=False));
 

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

1. Начните с RentalInventory первой таблицы и слева присоединитесь к следующей (вариант 2)

2. @Charlieface Итак, это будет выглядеть так?: ВНУТРЕННЕЕ СОЕДИНЕНИЕ (инвентарь для аренды ОСТАВИЛ JOIN CostumeInventory В RentalInventory. InventoryID = CostumeInventory. InventoryRecordID

3. Нет, он должен идти FROM RentalInventory LEFT JOIN CostumeInventory INNER JOIN RentalDetails ON ... INNER JOIN RentalClients ON ... ON... , т. Е. Другие таблицы должны быть между LEFT JOIN CostumeInventory и это ON условие

4. Спасибо, это сделало это! У меня также было неправильное совпадение данных, которое я исправил (почему попытка левого соединения ранее не сработала для меня). Теперь он отлично работает, ура!

Ответ №1:

Из того, что вы представили, это то, что, я думаю, у вас есть:

У RentalClient может быть много RentalDetails. Присоединиться: ClientID

RentalDetail использует несколько RentalInventory. Присоединиться: идентификатор аренды

Это та часть, где, по-видимому, существует несоответствие:

Таблица RentalInventory представляется ассоциативной таблицей, используемой для разрешения отношения «многие ко многим» между таблицей инвентаризации с Primarykey(SetID, InventoryID) и таблицей RentalDetails с PrimaryKey(RentalID)

Поскольку я не вижу таблицы инвентаризации в вашем запросе, есть 2 возможности:

  1. Вам не хватает таблицы инвентаризации с PrimaryKey(SetID, InventoryID), а таблица CostumeInventory является зависимым дочерним элементом этой таблицы, поэтому мы получаем:
 SELECT *
FROM RentalClients 
INNER JOIN RentalDetails ON RentalClients.ClientID = RentalDetails.ClientID
INNER JOIN RentalInventory ON RentalDetails.RentalID= RentalInventory.RentalID
INNER JOIN Inventory ON RentalInventory.SetID=Inventory.SetID 
and RentalInventory.InventoryID=Inventory.InventoryID
LEFT JOIN CostumeInventory on Inventory.SetID=CostumeInventory.SetID 
and Inventory.InventoryID=Inventory.InventoryID
 
  1. Вторая возможность заключается в том, что таблица CostumeInventory — это таблица инвентаризации с автоматически созданным InventoryRecordID и уникальным ограничением для InventoryID и SetID. Если это так, ваше соединение неверно, и это показывает, что во время моделирования была допущена ошибка — таблица RentalInventory должна иметь только поля RentalID и InventoryRecordID (для представления SetID и InventoryID). Чтобы устранить эту проблему с вашим запросом (не затрагивая модель), ваш запрос должен быть:

 SELECT *
FROM RentalClients 
INNER JOIN RentalDetails ON RentalClients.ClientID = RentalDetails.ClientID
INNER JOIN RentalInventory ON RentalDetails.RentalID= RentalInventory.RentalID
LEFT JOIN CostumeInventory ON RentalInventory.SetID=CostumeInventory.SetID and RentalInventory.InventoryID=Inventory.InventoryID
 

InventoryRecordID обычно представляет собой некоторый автоматически сгенерированный номер в большинстве систем, поэтому любое соединение с ним, вероятно, неверно. Он должен быть в SetID и InventoryID, поскольку это больше соответствует другой части уравнения для ассоциативной таблицы RentalInventory, первая из которых уже обработана RentalID . Опять же, это предполагает, что вариант №2 отражает истинную ситуацию.

Если нет уникального ограничения на поля SetID и InventoryID в таблице CostumeInventory, то, скорее всего, имеет место #1 выше.

В целом, MS Access по поведению через представление дизайна, как правило, добавляет много скобок / круглых скобок к запросам, что делает SQL сложным и немного более трудным для чтения при переходе к представлению SQL. Если вы можете, вы должны упростить для понимания — напишите это по-своему (используя псевдонимы, если необходимо) и замените его в представлении SQL, и это должно отразиться в представлении дизайна.

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

1. Спасибо! Это была ситуация №2. У меня действительно было несоответствие типа данных, которое я пропустил ранее с моими FK, и как только это было исправлено, оно заработало.