Поле SQL с несколькими идентификаторами другой таблицы

#sql #row #field

#sql #строка #поле

Вопрос:

Может кто-нибудь подсказать мне, как создать эту структуру базы данных. Вот пример:

 Table "countries":
id, countryname
1, "US"
2, "DE"
3, "FR"
4, "IT"
  

Теперь у меня есть другая таблица «продукты», и в ней я хотел бы сохранить все страны, где доступен этот продукт:

 Table "products":
id,productname,countries
1,"product1",(1,2,4) // available in countries US, DE, IT.
2,"product2",(2,3,4) // available in countries DE, FR, IT.
  

Мой вопрос:
Как мне спроектировать структуру таблицы в «продуктах», чтобы иметь возможность хранить несколько стран?

Моя лучшая идея — поместить туда строку, разделенную запятыми (т. Е. «1,2,4»), затем разделить эту строку для поиска каждой записи. Но я сомневаюсь, что это лучший способ сделать это?

РЕДАКТИРОВАТЬ: Спасибо всем за вашу помощь, потрясающе! Было трудно выбрать правильный ответ, в конце концов я выбрал Gregs, потому что он указал мне на объяснение соединения и привел пример, как его использовать.

Ответ №1:

Вам нужна таблица пересечений для этого отношения многие ко многим.

 Table Country
CountryID, CountryName

Table CountryProduct
CountryID, ProductID

Table Product
ProductID, ProductName
  

Затем вы внутренне объединяете все 3 таблицы, чтобы получить свой список стран и продуктов.

 Select * From Country 
Inner Join CountryProduct On Country.CountryID = CountryProduct.CountryID 
Inner Join Product On CountryProduct.ProductID = Product.ProductID
  

Ответ №2:

Без денормализации вам нужно будет добавить дополнительную таблицу

 Table Product countries
ProductID CountryID
1         1
1         2
1         4...
  

Ответ №3:

То, о чем вы говорите, — это нормализация. У вас структура «многие ко многим», поэтому вам следует создать другую таблицу, чтобы связать их. Вы никогда не должны (хорошо, практически никогда) использовать строки с разделителями для хранения списка значений в реляционной базе данных.

Вот пример настройки:

 product_countries table

productid | countryid
---------- -----------
1         | 1
1         | 2
1         | 4
2         | 2
2         | 3
2         | 4
  

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

Затем вы можете получить список поддерживаемых продуктов для идентификатора страны следующим образом:

 SELECT * FROM products, product_countries
WHERE products.id = product_countries.productid
AND product_countries.countryid = $cid
  

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

1. почему бы не использовать объединение? для меня это всегда выглядит немного странно

2. Логика при использовании JOIN была бы более запутанной для новичка в SQL, которым, очевидно, является OP. Конечно, JOIN тоже сработало бы, но без него логика яснее и ее легче понять.

3. Спасибо вам и всем остальным за помощь!! Да, SQL-новичок здесь. Один подвопрос: этот SQL-оператор кажется мне медленным — предположим, у меня более 100000 продуктов, не займет ли это много времени для перебора product_countries?

4. Не должно выполняться. Поскольку оба столбца являются как первичными, так и внешними ключами, они будут проиндексированы.

Ответ №4:

Вы также могли бы создать третью таблицу countries_products с полями country_id и product_id.

Ответ №5:

наилучший подход для реляционных баз данных заключается в следующем :

Одна таблица для стран, скажем, country_id, country_desc (country_id является основным)

одна таблица для продуктов, скажем, product_id, product_desc и столько столбцов, сколько вы хотите (product_id является основным)

если бы у вас наверняка была только одна страна, было бы достаточно иметь внешний ключ, указывающий на country_id в каждой строке product. Наличие внешнего ключа утверждает, что существует фактическая страна, имеющая идентификатор country_id, ссылающийся на таблицу country.

В вашем случае у вас есть несколько стран для продукта, поэтому добавьте отдельную ассоциативную таблицу product_id, country_id

оба ключа первичные, а также оба внешних.