我应该避免连接中的循环吗?

时间:2012-12-29 14:27:11

标签: sql database join business-objects

我记得在sql中连接表时,我被教导从不创建循环。 实际上,使用Business Objects,它甚至会告诉我在Universe中定义的模式中是否存在循环 我试图在网上搜索这个声明,但我找不到参考文献 为什么这样做很危险?

编辑:也许我太沉闷了。

我的问题不是关于用作“FOR LOOP”或类似的循环。 我在谈论SELECT语句中的这个WHERE子句:

WHERE TABLE1.foo = TABLE2.foo
  AND TABLE2.bar = TABLE3.bar
  AND TABLE3.baz = TABLE1.baz

如果绘制关系,您将在连接中看到“循环”。 从正确性和/或性能的角度来看,这是危险的吗? 谢谢大家。

编辑2:添加了一个示例。

我刚才想到了一个例子,也许这不是最好的,但我认为这有助于理解。

------------          -----------------      ----------------------
- DELIVERY -          - DELIVERY_DATE -      -  DELIVERY_DETAILS  -
------------          -----------------      ----------------------
- id       - <---     - id            - <----- date_id            -
- company  -     |----- delivery_id   -      - product            -
- year     -          - date          -      - quantity           -
- number   -          -----------------      - datetime_of_event  - 
- customer -                                 ----------------------
- ----------          

             1 <-----> N               1 <----> N
  • 在DELIVERY表格中,每次投放仅显示一次
  • 在DELIVERY_TABLE中,我们列出了处理交付的每个日期。因此,可以在几天内准备交货。
  • 在最后一张表中,我们详细介绍了每次发货。因此,在此表中,我们会跟踪与交付准备相关的每个事件

因此,每个表格的基数为1:N。

加入非常简单:

DELIVERY.id = DELIVERY_DATE.delivery_id AND 
DELIVERY_DATE.id = DELIVERY_DETAILS.date_id  

现在,假设我想加入另一个表,我在某个日期提供了一些其他信息。 我们来定义它:

------------  
- EMPLOYEE -
------------
- company  -
- year     -
- number   -
- date     -
- employee -
------------

现在联接应该是:

DELIVERY.id = DELIVERY_DATE.delivery_id AND 
EMPLOYEE.company = DELIVERY.company AND
EMPLOYEE.year = DELIVERY.year AND
EMPLOYEE.number = DELIVERY.number AND
EMPLOYEE.date = DELIVERY_DATE.date  

总而言之,我将结束让EMPLOYEE同时加入DELIVERY和DELIVERY_DATE,并在合并中加入循环。
我应该以这种方式重写它吗?

EMPLOYEE.company = DELIVERY.company AND
EMPLOYEE.year = DELIVERY.year AND
EMPLOYEE.number = DELIVERY.number AND
EMPLOYEE.date IN (SELECT date FROM DELIVERY_DATE d WHERE d.delivery_id = DELIVERY.id)  

编辑3:终于找到了一个链接

像往常一样,当你放弃搜索链接时,你会发现它 因此, this article 解释了所有内容。它与Business Objects有关,但内容是通用的 感谢您的所有时间。

2 个答案:

答案 0 :(得分:2)

编辑:我从更新中看到,这是一个特定于BO设计器的问题,其中一个表被多次使用,但是BO自动组合了连接子句,然后错误地(或者,更确切地说,无意地)限制了结果集。这个问题实际上与周期无关,本身就是在同一个查询中使用多个上下文中的实体。我将在下面留下我的原始答案,即使它没有真正解决OP的问题。

免责声明:这是一个非答案的答案,因为它既是答案,也是问题。它可能应该是一个评论,但你不能发表评论,除非你提出/回答问题,但由于我真的想要帮助,我会尽我所能,即使这不是事情在这里完成的方式。所以起诉我。

简短的回答是否定的,你不应该避免连接中的循环(或“循环”)。

更重要的是,构造查询以声明正确的逻辑条件以生成您正在寻找的数据。通常可以通过许多不同的方式建立相同的逻辑条件,因此有时候询问一种方式是否优于另一种方式是有意义的。当性能很重要时,这就变得特别重要。但首先,查询必须返回正确的结果集。如何实现这取决于底层架构。这就是你真正应该关注的内容。

在您的示例中,为什么EMPLOYEE在DELIVERY表中扮演角色?你为什么要加入这些专栏?这意味着员工与交货具有相同的“日期”是什么意思?我理解这是一个人为的例子,但我想说的是,连接是否在图中创建一个循环是完全(好的,主要)依赖于特定结果集的逻辑含义是。

在JOIN语法问题上,使用JOIN ... ON子句优于WHERE子句,因为它将您需要做的事情与数据过滤操作中的实体组合起来。

答案 1 :(得分:1)

嗯,你的问题很简单。您不应该使用where子句来执行连接。您应该使用on条款。您的联接可以表示为:

from Table1 join
     Table2
     on Table1.foo = Table2.foo join
     Table3
     on Table2.bar = Table3.bar and
        Table1.baz = Table3.baz

这是否合适取决于您的数据结构。有时它是。你不应该担心它。

顺便说一下,我不会将此称为“循环”,它与编程中的“for循环”和SQL中的嵌套循环连接非常相关。您可以将此称为连接条件中的循环。

Wmax。 。 。至于新的连接语法。这不仅仅是品味问题。 from子句中的“,”表示“交叉连接”。在大多数情况下,这是一项非常昂贵的操作。要明确你想要完成的事情要好得多:

FROM A cross join B

比其意图更清楚:

FROM A, B

其次,如果你离开“,”,你仍然有有效的语法:

FROM A B

但是,这意味着非常不同(将别名B分配给表A)。

第三个原因是最重要的原因。旧语法无法表达left outer joinright outer joinfull outer join

因此,为了编写更清晰的查询,以避免错误,并访问更好的功能,您应该学习新的语法。