Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/76.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/26.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 内部连接vs交叉连接vs交叉应用_Sql_Sql Server_Join - Fatal编程技术网

Sql 内部连接vs交叉连接vs交叉应用

Sql 内部连接vs交叉连接vs交叉应用,sql,sql-server,join,Sql,Sql Server,Join,SQL的乐趣之一是,通常有多种方法来做同一件事,那么哪种方法是“最好的” 在本例中,我从一个“导入”表中插入记录,并为它们提供“查看器”的默认安全级别(在不同的数据库中可能有不同的密钥ID)。我至少可以用三种不同的方法(可能还有更多的方法):交叉连接、交叉应用和内部连接。对于性能或设计方面的最佳选择,有何建议?我倾向于十字架 这个问题可能已经得到了回答,但我找不到它,最近我在发展过程中不断遇到这种需要,所以我不妨学习最好的方法 下面是3个示例语句。加入SecRole表的最佳方式是什么 INSER

SQL的乐趣之一是,通常有多种方法来做同一件事,那么哪种方法是“最好的”

在本例中,我从一个“导入”表中插入记录,并为它们提供“查看器”的默认安全级别(在不同的数据库中可能有不同的密钥ID)。我至少可以用三种不同的方法(可能还有更多的方法):交叉连接、交叉应用和内部连接。对于性能或设计方面的最佳选择,有何建议?我倾向于十字架

这个问题可能已经得到了回答,但我找不到它,最近我在发展过程中不断遇到这种需要,所以我不妨学习最好的方法

下面是3个示例语句。加入SecRole表的最佳方式是什么

INSERT INTO LocStaff (LocationID, StaffID, SecRoleID)
    SELECT i.LocationID, s.StaffID, sr.SecRoleID
    FROM IntStaff i
        JOIN Staff s ON i.EmployeeID = s.StaffNumber
        CROSS JOIN SecRole sr
    WHERE sr.Name = 'Viewer' 

INSERT INTO LocStaff (LocationID, StaffID, SecRoleID)
    SELECT i.LocationID, s.StaffID, sr.SecRoleID
    FROM IntStaff i
        JOIN Staff s ON i.EmployeeID = s.StaffNumber
        JOIN SecRole sr ON sr.Name = 'Viewer'

INSERT INTO LocStaff (LocationID, StaffID, SecRoleID)
    SELECT i.LocationID, s.StaffID, sr.SecRoleID
    FROM IntStaff i
        JOIN Staff s ON i.EmployeeID = s.StaffNumber
        CROSS APPLY (SELECT TOP 1 SecRoleID FROM SecRole WHERE Name = 'Viewer') sr

前两者是等价的。在这种情况下,是否使用内部联接或交叉联接实际上是一个偏好问题。我想我通常会使用交叉连接,因为表之间没有真正的连接条件

注意:如果意图是表之间具有匹配条件的“真实”
内部联接
,则不应使用
交叉联接

交叉应用
没有执行相同的操作。它只选择了一行。如果您的目的是获得最多一个匹配行,则使用
交叉应用
。如果目的是只获得一个匹配行,那么使用
outerapply

只有在表中没有任何公共列(不是最佳结构设计!)或需要所有可能的情况下,我们才使用交叉连接(或仅使用关键字连接)。我不知道您的表结构,但我假设表SecRole没有Staff和InsStaff的外键或公用键。在本例中,我将在这里使用一个右连接(外部连接)来获得Staff和InsStaff之间第一个内部连接的所有结果,然后将它们放在SecRole所需记录的旁边

这是右连接的概念

我不认为在大多数情况下,
交叉连接
可以与其他两个进行比较。因此,你的问题变成了
内部连接vs交叉应用
,如下所示:不完全重复,因为另一个关注的是一般何时使用交叉应用,但是如果你的断言正确,交叉连接应该被彻底拒绝,那么我认为另一个帖子建议交叉应用应该比内部连接更快。当只提取一条记录时会出现这种情况吗?或者实际上没有区别,这更像是个人偏好?在尝试比较这些不同操作的上下文中,您的示例查询没有意义。实际上,您通过三种不同的方式将常量值添加到查询中。您也可以在select中使用局部变量或子查询
SecRoleID
与查询的其余部分无关。您是正确的。我正在尝试将适当的SecRoleID添加到插入的每个记录中。它可以是一个局部变量(在Name='Viewer')或子查询中使用SELECT来设置它。你觉得这两种方法中的任何一种都比交叉应用更好吗;听起来像是第四种方法。您可能不知道这一点(因为我没有说明),但由于SecRoleID在目标表中不为NULL,因此我确实在寻找一个匹配的行。你是说交叉应用程序(前1个)可能返回空值,因此它不是合适的解决方案吗?@ScottDuncan。否。
交叉应用(前1)
满足您的要求。其他人似乎不会<如果表之间不匹配,code>OUTER APPLY
将返回
NULL
值。您提到前两个值是等效的。这是真的吗,还是交叉连接在过滤之前连接所有行,而内部连接只连接一个所需行?不管怎样,我倾向于交叉应用,因为它似乎最清楚地表明了意图。我担心性能,但上面提供的链接SqlZim似乎表明交叉应用程序无论如何应该有更好的性能。@ScottDuncan。SQL语句描述结果集。优化选择最佳的执行计划。我所熟悉的每一个优化器都会将这两者视为相同的。FWIW我只是想在这里写一个注释,因为它被提出来了,优化器似乎并不总是在内部连接和交叉连接之间选择最佳的执行计划,即使数据集是相同的。在我的例子中,两个表中有一列对于所有行都是相同的常量值。因此,该列上的交叉连接和内部连接是相同的。但是,如果该列在以后的联接中使用,那么优化器似乎没有保留其已修复的知识,因此进行了许多不必要的比较,而对于内部联接,优化器“记住”它们匹配。问题是,当SecRole和其他表之间没有公共键时,最好的方法是从SecRole中恰好附加一个值,那么“将它们放在SecRole的(恰好一个)所需记录旁边”是什么意思呢?我的例子展示了三种可能的方法,我想知道哪一种是最好的,或者还有第四种更好的方法吗?你是在建议一个正确的外部连接到SecRole吗?既然没有公共键,ON子句会是什么样的呢?这比WHERE过滤器的交叉连接,或者ON子句中过滤器的左连接更好吗?对不起,我指的是内部连接,而不是左连接(显然,您只有5分钟的时间来捕捉错误并将其修复到位)。