#sql #ms-access #join
#sql #ms-access #Присоединиться
Вопрос:
У меня нет опыта программирования или базы данных (кроме как в качестве конечного пользователя), и я создаю базу данных с доступом в 365. У меня очень ограниченное представление о SQL.
Я написал запрос с несколькими таблицами для создания отчета, и он в основном работает. Он вернет все запрошенные данные для всех таблиц, кроме одной (CostumeInventory)
. Для этой таблицы он создает столбцы (ItemName, Description, Condition, RentalRate, ReplacementValue)
, но строки в этих столбцах пустые. . В таблице CostumeInventory они обязательны, имеют значение short text, и все они содержат данные.
При разработке запроса, если я щелкну по соединению с CostumeInventory, у меня будет выбран вариант 3. 1 ничего не возвращает, а 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 возможности:
- Вам не хватает таблицы инвентаризации с 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
- Вторая возможность заключается в том, что таблица 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, и как только это было исправлено, оно заработало.