【问题标题】:Why and when to use CROSS JOIN instead of INNER JOIN with UPDATE statements?为什么以及何时在 UPDATE 语句中使用 CROSS JOIN 而不是 INNER JOIN?
【发布时间】:2013-04-10 05:43:57
【问题描述】:

在 T-Sql 中编码自三个多月以来,我第一次看到在某些代码中的 UPDATE 语句中使用 CROSS JOIN,但我无法弄清楚它的用途这种结构的例子。

有人知道吗?

编辑:这是一个我还不能理解的示例代码。

UPDATE a
SET a.COL1 = b.COL1
FROM Table1 AS a
CROSS JOIN Table2 AS b

代码中还有其他更新提供了WHERE 子句,例如:

UPDATE a
SET a.COL1 = b.COL1
FROM Table1 AS a
CROSS JOIN Table2 AS b
WHERE condition_on_columns_from_a_and_from_b

重点是对于 Table1 的每一行,带有过滤的交叉连接上的选择会返回多行。

我对这种行为的理解有点困惑。

PS:表 Table1 占用超过 5 GB 的空间..

【问题讨论】:

  • 听起来您已经有了一个示例:您正在查看的查询。它有什么作用?
  • 你了解交叉连接和内连接的区别吗?
  • 听起来像是不确定行为的秘诀,但如果没有看到它就很难分辨。
  • 这是因为我无法理解更新的真正作用,我才提出这个问题。是的,当它与 SELECT 语句相关时,我了解不同类型的连接之间的区别。在我看来,更新的行为可能是不确定的,但我不太确定,我将编辑上面的描述以包含一些 samlpe 代码。

标签: sql sql-server tsql


【解决方案1】:

我没有充分的理由可以想象这样做。查询要么写错了,要么只是为了减慢系统速度或使目标表的数据无效(或者只是为了看看它做了什么)。

它可能会将 Table1 中每一行的 COL1 设置为与 Table2 的 COL1 相同的单个随机值(尽管可能是第一个或最后一个这样的值)。但是这样做会非常效率低下(除非 SQL Server 更高版本中的优化器已经优化了这种无用的情况,否则我自己已经有好几年没有测试过了)。

【讨论】:

    【解决方案2】:

    交叉连接生成两个表的笛卡尔积。这意味着它将表 A 的每一行与表 B 的每一行组合在一起。当表 A 有 n 行而表 B 有 m 行时,结果集有 n*m 行。

    【讨论】:

    • 是的,但问题是:SELECT 与 CROSS JOIN 一起使用时的行为如何?
    【解决方案3】:

    要了解用例,您需要查看数据。如果我是肯定的,我可以很容易地看到使用第一次更新 tableb 总是并且只包含一条记录。对于一条记录没有要连接到表 A 上的字段的情况尤其如此。在这种情况下,您将使用表 b 中该字段的值更新表 a 中的所有字段。通常这种更新所有记录的事情只会用于重置值。

    要查看将更新的内容,请执行以下操作:

    UPDATE a
    SET a.COL1 = b.COL1
    --select a.COL1,b.COL1, *
    FROM Table1 AS a
    CROSS JOIN Table2 AS b
    WHERE condition_on_columns_from_a_and_from_b
    

    现在您可以只运行选择部分来查看 a.col1 将被替换为什么值,并查看表中的其他字段以查看连接是否正确以及 where clasue 是否正确。这将帮助您了解 corss join 的作用。然后,您可以暂时将交叉连接替换为左连接和内连接,以了解它与其他类型的连接不同的行为。玩一会儿选择,直到你真正理解发生了什么。如果没有在 cmets 中进行选择,我从不编写更新,因此我可以确保在将代码移动到 prod 之前更新我认为应该是的内容。如果您像我一样编写复杂的更新,这可能涉及十或十五个连接和几个 where 条件,则尤其如此。

    【讨论】:

      【解决方案4】:

      好的,使用这个查询:

      UPDATE a
      SET COL1 = b.COL1
      FROM Table1 AS a
      CROSS JOIN Table2 AS b
      WHERE condition_on_columns_from_a_and_from_b
      

      如果我们采用由a CROSS JOIN b 形成的集合(在考虑FROM 子句之前),那么我们有一个笛卡尔积,其中来自a 的每一行都与来自b 的每一行配对。

      如果我们现在考虑WHERE 子句-除非这个WHERE 子句足以保证a 中的每一行只表示一次,那么我们将得到一个不确定的结果。也就是说,如果集合中有两行都来自a 的同一行(但来自b 的不同行),那么就无法确定这两行中的哪一行将用于计算SET a.COL1 = b.COL1 分配。

      如果我们有以下情况,我认为它甚至不能保证:

      UPDATE a
      SET COL1 = b.COL1, COL2 = b.COL2
      FROM --As before
      

      b 中的 相同 行将用于两个分配。

      以上所有情况都适用于 any UPDATE 使用 T-SQL FROM 子句扩展的语句 - 除非你小心地约束你的连接条件,然后对同一个条件进行多个赋值行可能是可能的。但是CROSS JOIN 似乎使它更有可能发生。如果发生这种情况,SQL Server 会发出no 诊断消息。

      【讨论】:

        猜你喜欢
        • 2010-11-11
        • 2011-09-25
        • 1970-01-01
        • 2012-04-05
        • 1970-01-01
        • 1970-01-01
        • 2013-07-19
        相关资源
        最近更新 更多