【问题标题】:Join on 1=1 versus cross join加入 1=1 与交叉加入
【发布时间】:2014-01-09 19:51:50
【问题描述】:

我正在将 postgresql 中的一个大表连接到一个包含 1 行的表中。是的,我知道我可以从这个单行表中获取值并将它们放入我写出的查询中,但是有 210 列。

所以我的问题是:我应该使用交叉连接还是在重言式上使用常规连接(1 = 1 或其他东西)将单行表连接到所有内容。这两种方式中的任何一种都会变慢吗?

或者有第三种更快的方法吗?

【问题讨论】:

  • 到底是什么问题?您需要在连接条件中包含所有 210 列吗?
  • 使用cross join 明确您的意图。否则明年你(或不得不更改代码的人)会想知道那个愚蠢的1=1 应该是什么意思。
  • 衡量寻求解决方案的表现。
  • 如果每行的 210 列的值相同,为什么不使用 2 个查询?
  • 据我所知,交叉连接更快

标签: sql join


【解决方案1】:

需要注意的一点是,如果其中一个表为空,则交叉连接将导致一个空表。如果您的一个表可能是空的并且您仍然需要记录,则您可能需要 1=1 上的外连接(例如左、右或全连接)。

【讨论】:

  • ☝️就在这里,这是一个巨大的警告和一个很大的问题
【解决方案2】:

1=1 存在的原因是通过将字符串连接在一起来更容易地创建动态 sql 语句(当然还有参数化等常用的保护措施)。

有一个带有1=1 的预定义WHERE 子句允许在SQL 中添加额外的WHERE 条件,而无需先检查WHERE 子句是否存在,SQL 引擎通常会优化@987654324 @ 所以没有性能差异。

在任何其他情况下,1=1 通常是无害的,但不是特别有用。

【讨论】:

  • 这不能回答 OP 的问题。问题是:select * from t1 join t2 on 1=1select * from t1 cross join t2 有什么区别。
  • 是的。看我回答的最后一句话。
【解决方案3】:

它们应该执行和表现相同 - 区别在于开发人员语义

这是一个示例演示:

-- Setup
DECLARE @Codeset TABLE (id INT, [name] VARCHAR(50));
DECLARE @Student TABLE (id INT, [name] VARCHAR(50), age INT);

INSERT INTO @Codeset  
VALUES (1, 'HomeRoom');

INSERT INTO @Student  
VALUES (1, 'Jolly', 20), 
       (2, 'Sally', 22);

假设我们想要从@Student 取回每一行,并从@Codeset 取回名称值:

| id | name  | age | name     |
|----|-------|-----|----------|
| 1  | Jolly | 20  | HomeRoom |
| 2  | Sally | 22  | HomeRoom |

当任一表有 0、1 或 1+ 条记录时,以下任何语法都可以完成此操作:

-- INNER JOIN 1=1
SELECT s.id, s.[name], s.age, c.[name]
FROM @Student s
INNER JOIN @Codeset c ON 1=1

-- Multiple From tables
SELECT s.id, s.[name], s.age, c.[name]
FROM @Student s,
     @Codeset c

-- CROSS JOIN
SELECT s.id, s.[name], s.age, c.[name]
FROM @Student s
CROSS JOIN @Codeset c

在这种情况下,您应该更喜欢 CROSS JOIN 尽可能明确地表明您从多个不相关的表中构建单个 select 语句的意图

注意CROSS JOIN 的输出与INNER JOIN ON 1=1 相同。两者都产生两个行集中所有行的笛卡尔积,所以如果一个表是空的,结果也是如此。

如果@Students有记录时需要保证结果,但@Codeset可能为空,则需要使用LEFT JOIN ON 1=1

另见Correct way to select from two tables in SQL Server with no common field to join on

【讨论】:

    【解决方案4】:

    仅基于我编写大量sql后的经验。 inner join on 1=1 比简单的 cross join 快得多。

    【讨论】:

    • 请详细说明。
    猜你喜欢
    • 2013-03-11
    • 1970-01-01
    • 2016-05-24
    • 1970-01-01
    • 2021-10-25
    • 2020-12-12
    • 1970-01-01
    • 1970-01-01
    • 2015-11-29
    相关资源
    最近更新 更多