Как выполнить SQL-запрос, используя столбцы из связанной таблицы?

#tsql

#tsql

Вопрос:

У меня есть три связанные таблицы SQL, упрощенные, они выглядят следующим образом:

 ShopTable
  [ShopID]

ShelfTable
  [ShelfID]
  [ShopID]

InventoryTable
  [ShelfID]
  [Value]
  

[shopId] и [ShelfID] являются отношениями. Теперь то, что я хочу сделать, это получить СУММУ [Value] для одного [shopId], но это, очевидно, не сработает, поскольку [shopId] не является частью InventoryTable:

 SELECT SUM([Value]) WHERE [ShopID] = '1'
  

Как мне написать запрос для фильтрации InventoryTable с использованием shopId?

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

1. «[shopId] и [ShelfID] являются отношениями» — это не так. Они используются в качестве первичных / внешних ключей. Во фразе «реляционная база данных» слово «реляционный» происходит из математической теории, и эквивалентом в мире баз данных SQL является таблица (хотя есть места, где SQL не соответствует математической модели)

2. @Damien, ах, извините за неправильное использование терминов.

Ответ №1:

 SELECT  SUM(i.value)
FROM    shelfTable s
JOIN    inventoryTable i
ON      i.shelfId = s.shelfId
WHERE   s.shopId = 1
  

Ответ №2:

Это фундаментальный вопрос об отношениях между таблицами, поэтому я приведу некоторые подробности, надеясь, что вы сможете использовать некоторые из этих идей при написании SQL-запросов в будущем.

Давайте сначала начнем с одной базовой вещи. [shopId] может ссылаться на два разных, но связанных столбца, один в [ShopTable] и один в [ShelfTable]. То же самое относится и к [ShelfID]. Полезно всегда указывать таблицу.

Вы описываете [shopId] и [ShelfID] как «отношения». Как прокомментировал Damien_The_Unbeliever, эти столбцы фактически представляют собой две пары первичного и внешнего ключей. То есть [ShelfTable].[ShelfID] идентифицирует запись «shelf» и [InventoryTable].[ShelfID] связывает «элемент инвентаря» (что бы это ни было) с «полкой». (Не всегда возможно интерпретировать строки в базе данных таким наивным образом, но я готов предположить, что я не слишком далек от реальности.)

Аналогично, каждая «полка» принадлежит одному «магазину» и [ShelfTable].[shopId] относится к этому конкретному «shop». Обратите внимание, что, поскольку у нас уже есть значение [shopId] (я буду называть его «@MyShopID»), нам даже не нужна [ShopTable] здесь. Мы можем просто использовать [ShelfTable].[shopId] для фильтрации по интересующим нас «полкам».

Вы просите получить общую сумму [InventoryTable].[Значение] для одного значения [shopId], но [shopId] не отображается в [InventoryTable]. Вот где вступает в игру ваше (внутреннее) объединение. Вы знаете, что будете суммировать значения из [InventoryTable], но вы должны указать конкретный «магазин». Вы указываете @MyShopID для [ShelfTable].[ShelfID], который выполнит вашу фильтрацию в [InventoryTable] за вас.

И последнее, перед составлением запроса. Я предполагаю, что вы не слишком упростили свои таблицы, и что [Value] — это общая стоимость каждого «элемента инвентаря», а не просто значение единицы. Если бы это было не так, нам пришлось бы умножать значения на величины и т.д., Но я позволю вам проверить вашу собственную работу здесь.

Итак, вот что мы делаем:

  • Мы выбираем FROM [InventoryTable]
  • но мы INNER JOIN обращаемся к [ShelfTable] on [ShelfID] из обеих таблиц
  • и нам нужны только «полки» из одного «магазина», т.Е. WHERE [ShelfTable].[ShopID] = @MyShopID
  • и тогда мы SELECT SUM([InventoryTable].[Value])

и мы закончили. В SQL давайте уберем скобки, предоставим некоторые псевдонимы таблиц, и мы получим запрос, который выглядит следующим образом:

 SELECT SUM(inv.Value)
FROM InventoryTable AS inv
INNER JOIN ShelfTable AS shf ON shf.ShelfID = inv.ShelfID
WHERE shf.ShopID = @MyShopID
;
  

Вот несколько важных моментов, которые следует учитывать. Обратите внимание, что сначала мы обработали предложение FROM . Вы всегда будете хотеть это делать.

Вам также понадобится «управляющая таблица» для начала, в данном случае [InventoryTable]. Другие таблицы в вашем объединении добавляют дополнительную информацию и предоставляют вам средства для фильтрации, но в остальном не мешают вашему подведению итогов. Более сложные запросы не предлагают такой очевидной роскоши, но здесь мы не слишком увлекаемся.

Вы также заметите, только вкратце, что, поскольку [ShelfID] является первичным ключом в [ShelfTable], эти [ShelfID] являются уникальными значениями в [ShelfTable], и поэтому каждая «инвентарная» вещь принадлежит одной «полке». Таким образом, объединение не приведет к двойному подсчету значений. Это полезно помнить, когда вы не имеете дело с первичными и внешними ключами, как мы делаем здесь.

Надеюсь, это поможет. И я надеюсь, что я не показался вам слишком педантичным.

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

1. Не слишком педантично, это отличное объяснение, спасибо!! И да, значение упрощено, на самом деле это СУММА ([Количество] * [Цена] / [PriceUnit] * [взвешивание]), но это была самая простая часть 🙂

2. Спасибо! И уфф, это много etc. чтобы разобраться! 🙂