我有两个表,两个表都有一个复合主键:
我可以使用OrderNr和OrderNr将两个表结合在一起吗?OrderNr和OrderNr都是复合主键的一部分?
答案 0 :(得分:1)
是的,但是您可能会发现从每个表中得到的行在合并在一起构成唯一组合时会重复。这称为笛卡尔积
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表示行是唯一的)也会导致结果集增加-从A到2行custnr 1乘以B中custnr 1的2行,总共得到4行
它也可以与普通/ naturla连接一起使用吗?
当ON条件有效时,普通联接(INNER,LEFT OUTER,RIGHT OUTER,FULL OUTER)将联接来自两个表或子查询的行。 ON中的子句就像WHERE子句一样,是的-因为它表示对或错(谓词)的语句。如果该语句为true,则将行合并。您甚至不必处理表中的数据-您甚至可以说a JOIN b ON 1=1
,A中的每一行都将与B中的每一行联接。如前所述,JOINS在以下位置不涉及主键:所有这些,尽管主键通常依赖于索引,并且这些索引可用于加快连接速度,但它们对它并不重要。
存在其他联接(CROSS,NATURAL ..); CROSS联接类似于上面的1 = 1示例,您没有指定ON,根据设计,A中的每一行都与B中的每一行相连。自然连接是避免使用的一种,恕我直言-数据库将在两个表中查找相同的列名并将它们联接。问题是,如果有人向两个表添加名称相同但内容/含义不同的列,将来事情可能会停止工作。我遇到过的严肃的生产系统都没有使用NATURAL Join。如果要连接的列的名称相同,则可以不用键入内容,而使用-SELECT * FROM a JOIN b USING (col)
-这里A和B都有一个名为col
的列。使用具有一些优势,尤其是相对于NATURAL join而言,它的优势在于,如果另一列与现有名称相同,但它也不会崩溃,但是它也具有一些贬低者-您不能说USING(col) AND ...
。大多数人只是坚持写下去,而忘记使用
NATURAL联接也不使用主键。没有一种联接样式(我知道)可以查看两个表之间的外键关系并将其用作联接条件
然后是真的吗,如果我尝试联接两个表的主键和外键,它的工作原理就像一个“ where”命令?
很难理解您的意思,但是,如果您的意思是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中的值。不需要主键即可解决
答案 1 :(得分:0)
如果它们之间存在逻辑关系,则可以联接任何表
select *
from t1
JOIN t2
on t1.ORderNr = t2.OrderNr
尽管OrderNr
本身不能提供表之间的唯一性,但是您的数据将成倍增加。
让我们假设您有2个OrderNr(在t1上值为1)和5个OrderNr(在t2上值为1),当您加入它们时,您将获得2 x 5 = 10个记录。
答案 2 :(得分:0)
您的数据模型类似于通常称为“扇形陷阱”的问题。 (如果您有一个仅由OrderNr
键控的“订单”表,如果它确实是一个粉丝陷阱)。
无论哪种方式,都是相同的问题-订单/客户与订单/项目之间的关系不明确。您无法确定哪些客户订购了哪些物品。
从技术上讲,可以联接这些表-您可以联接任何列,无论它们是否为键列。问题是,除非您有更多条件和其他表格没有告诉我们,否则您的结果可能没有意义。
例如,仅在t1.OrderNr = t2.OrderNr
上的简单联接将返回行,指示与该订单相关的每个客户都已订购与该订单相关的每个项目。如果那是您想要的,那么您在这里没有问题。