【问题标题】:INNER JOIN should happen only when a condition is fulfilledINNER JOIN 仅在满足条件时才发生
【发布时间】:2013-06-11 21:15:53
【问题描述】:

如果不满足条件,我正在尝试“短路”INNER JOIN。

我尝试了什么:
我发现如果在“ON”条件下,Left Join 前面有一个 False 子句,则 LEFT JOIN 失败。因此,我尝试用 LEFT OUTER JOIN 模拟 INNER JOIN,WHERE 子句得到如下执行计划:

DECLARE @a nvarchar(4) = 'All'

SELECT A.*
FROM [dbo].[your_table] A
LEFT JOIN [dbo].[your_table_2] B
     ON @a <> 'All'
WHERE A.City_Code = CASE WHEN @a <> 'All' 
                    THEN B.City_Code 
                    ELSE A.City_Code END

这将使左连接“短路”并且永远不会发生。执行计划如下:

但是当我尝试通过将变量声明为“Al”而不是“All”来执行相同的语句时,我发现执行计划仍然相同。

我不知道 Join 是否发生在初始步骤中?

我想要什么:
我想知道上述方法是否正确?是否真的使 INNER JOIN 短路?
我基本上希望只有当变量不是“全部”时才在两个表之间进行内部连接,否则它不应该连接并继续进一步。我已经尝试过使用“OR”(短路)和“IN”(应用过滤器),但如果 IN 子句中有太多项目,性能会降低。
请帮助我并告诉我我的方法是否有任何错误。

样本数据:

只有当变量 'all' 时我才应该得到 INNER JOIN 结果

当变量 = 'All' 时,我应该得到表 A 即

注意:我已经简化了这个查询,因此看起来很简单的 if 语句就可以做到。实际上,我有 53 个参数需要检查和运行 JOINS。加上一个查询的结果集必须与另一个查询连接,即我在此之前还有其他几个 JOIN 条件:)

【问题讨论】:

  • 不确定你想做什么,但从“TABLE SCAN”值我可以说你的表没有索引,因此连接可能很慢。我已经以任何一种方式加入了数百万条记录,它对我来说永远不会变慢,你在“on”中尝试做的事情实际上会导致表格的笛卡尔积。
  • @SumitGupta 我想做的是“短路”。如果变量是“所有”,则笛卡尔积甚至不应该发生,连接必须被忽略。
  • 如果您向我们提供了示例数据和预期输出的示例,那么您会更容易理解您想要什么。
  • 我已经包含了示例数据。这只是为了试用。实际项目数据更大,表格也很复杂。
  • 据我了解,您正在搞乱您的需求和数据库结构。如果您在没有其他条件的情况下获得该变量,如果条件为假,它将为表 b 提供空值,如果条件为真,它会给出笛卡尔积,然后根据您的 where 条件进行过滤。更好地创建一个过程并在变量上放置 2 个带有条件的查询。因此,一个 queyr 将加入,而另一个则没有加入。

标签: sql sql-server tsql left-join inner-join


【解决方案1】:

你有没有尝试过类似的东西

SELECT  A.*
FROM    [dbo].[your_table] A
WHERE   EXISTS  (
            SELECT  1
            FROM    [dbo].[your_table_2] B
            WHERE   A.City_Code = B.City_Code
        )
OR  @a = 'All'

【讨论】:

  • 如果我有 @a 'All',这不会给我一个 INNER JOIN 结果吗?
  • 如果@a 'All',那么它将确保只返回表B中存在的表A的结果,这与INNER JOIN相同。
  • 如果table_1和table_2都有重复数据怎么办? INNER JOIN 会给我一个包含 City_Code 的所有组合的结果,但这不会。我在我的数据集上尝试了您的查询,结果与我从 INNER JOIN 得到的结果不同。您是否希望我在问题中也描述表架构和数据?
【解决方案2】:

你试过case语句吗? CASE 或 DECODE 通常类似于 SQL 中的 IF-ELSE 语句。

【讨论】:

  • 所以,我已经简化了这个查询,因此看起来简单的 IF/CASE 语句可以做到。实际上,我有 53 个参数需要检查和运行 JOINS。加上一个查询的结果集必须与另一个查询连接,即我在此之前还有其他几个 JOIN 条件:)
  • 是的,所以我想说的是,LEFT JOIN ON CASE STATEMENT,在里面,检查 INNER JOIN,如果 INNER JOIN 返回值,意味着,这是真的 TRUE,因此,LEFT必须检查 JOIN 条件,否则 LEFT JOIN 必须失败。这是你想要达到的目标吗?
  • 或者你可以像 LEFT JOIN ON WHERE EXISTS 一样,然后 INNER JOIN,如果这里没有值,则意味着 EXISTS 条件失败。我对语法感到抱歉。
猜你喜欢
  • 1970-01-01
  • 2018-01-22
  • 1970-01-01
  • 2011-05-13
  • 2021-08-21
  • 2021-08-25
  • 2012-12-25
  • 1970-01-01
相关资源
最近更新 更多