Можем ли мы объединить две части двух составных первичных ключей вместе? - PullRequest
0 голосов
/ 06 февраля 2019

У меня две таблицы, обе имеют составной первичный ключ:

  1. OrderNr + CustNr
  2. OrderNr + ItemNr

Могу ли я присоединиться к обеимтаблицы с OrderNr и OrderNr, каждая из которых является частью составного первичного ключа?

Ответы [ 3 ]

0 голосов
/ 06 февраля 2019

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

select *
from t1
JOIN t2 
  on t1.ORderNr = t2.OrderNr

Хотя если OrderNr не может обеспечить уникальность между таблицами, ваши данные будут умножены.

Допустим, у вас есть 2 OrderNr со значением 1 на t1 и 5 OrderNr со значением 1 на t2, когда вы присоединитесь к ним, вы получите 2 x 5 = 10 записей.

0 голосов
/ 06 февраля 2019

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

В любом случае, это та же проблема - отношения между Заказом / Клиентами и Заказом / Элементаминеоднозначный.Вы не можете сказать, какие клиенты заказали какие товары.

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

Например, простое объединение только на t1.OrderNr = t2.OrderNr будет возвращать строки, указывающие каждыйКлиент, связанный с заказом, заказал каждый товар, связанный с заказом.Если это то, что вы хотите, у вас нет проблем здесь.

0 голосов
/ 06 февраля 2019

Да, но вы можете обнаружить, что вы получаете строки из каждой таблицы, которые повторяются при объединении в уникальную комбинацию.Это называется декартовым произведением

Table A
OrderNr, CustNr
1,C1
1,C2
2,C1
2,C2

TableB
OrderNr,ItemNr
1,i1
1,i2


SELECT * FROM a JOIN b ON a.OrderNr = b.OrderNr

1,C1,1,i1
1,C1,1,i2
1,C2,1,i1
1,C2,1,i2

Это происходит потому, что составные первичные ключи могут содержать повторяющиеся элементы, если комбинация элементов уникальна.Соединение только с одной частью PK, и эта часть является элементом, который повторяется (мой custnr 1 повторяется дважды в каждой таблице, хотя itemnr и CustNr означают, что строки уникальны) приводит к умноженному результату - 2 строки из Acustnr 1, умноженные на 2 строки из B, которые custnr 1, дают в общей сложности 4 строки

Работает ли это и с обычным / натурным соединением?

Обычные объединения (INNER, LEFT OUTER, RIGHT OUTER, FULL OUTER) объединят строки из двух таблиц или подзапросов, когда условие ON выполнено.Предложение в ON похоже на предложение WHERE, да, в том смысле, что оно представляет утверждение, истинное или ложное (предикат).Если утверждение верно, строки объединяются.Вам даже не нужно делать это с данными из таблиц - вы даже можете сказать a JOIN b ON 1=1, и все строки из A будут объединены с каждой строкой из B. Как уже отмечалось, первичные ключи вообще не участвуют в JOINS,хотя первичные ключи часто полагаются на индексы, и эти индексы могут использоваться для ускорения соединения, но они не являются жизненно важными для него.

Существуют и другие объединения (CROSS, NATURAL ..);соединение CROSS похоже на приведенный выше пример 1 = 1, вы не указываете ON, каждая строка из A соединяется с каждой строкой из B, в соответствии с дизайном.ИМХО - НАТУРАЛЬНОЕ СОЕДИНЕНИЕ, ИМХО - база данных будет искать имена столбцов, которые являются одинаковыми в обеих таблицах, и объединяться в них.Проблема в том, что в будущем вещи могут перестать работать, если кто-то добавит столбец с тем же именем, но разным содержанием / значением в две таблицы.Ни одна серьезная производственная система, с которой я когда-либо сталкивался, не использовала NATURAL join.Вы можете обойтись без некоторого набора текста, если ваши столбцы для объединения названы одинаково, с помощью USING - SELECT * FROM a JOIN b USING (col) - здесь и A, и B имеют столбец с именем col.ИСПОЛЬЗОВАНИЕ имеет некоторые преимущества, особенно перед естественным соединением, в том, что оно не разваливается, если другой столбец с тем же именем, что и существующий, но у него тоже есть некоторые недоброжелатели - вы не можете сказать USING(col) AND ....Большинство людей просто продолжают писать ON и забывают, что ИСПОЛЬЗОВАНИЕ

NATURAL join также НЕ использует первичные ключи.Не существует стиля соединения (о котором я знаю), который бы смотрел на отношение внешнего ключа между двумя таблицами и использовал его в качестве условия соединения

И тогда верно ли, что если я попытаюсь присоединиться к Первичномуключ и внешний ключ двух таблиц, что он работает как команда "где"?

Трудно понять, что вы подразумеваете под этим, но если вы имеете в виду, что A JOIN B ON A.primarykey = B.primary_key_in_a, тогда это сработает, конечно.Если вы имеете в виду A CROSS JOIN B WHERE A.primarykey = B.primary_key_in_a, то это тоже сработает, но я бы определенно избегал этого - никто не пишет SQL таким образом, и общее преимущество состоит в том, чтобы отказаться от использования WHERE для создания условий соединения (вы все еще видите, что люди пишутпо старому стилю FROM a,b WHERE a.col=b.col, но это также сильно не рекомендуется), и вместо этого включите их в ON

Итак, в итоге:

SELECT * FROM a JOIN b ON a.col1 = b.col2

Объединяет все строки из a со всеми строками изb, где значения в col1 равны значениям в col2.Для работы с этим не требуется никаких первичных ключей

...