4

我记得我被教导在 sql 中加入表时永远不要创建循环。实际上,使用业务对象它甚至可以告诉我在 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:终于找到了一个链接

像往常一样,当您放弃搜索链接时,您会找到它。
所以,这篇文章解释了一切。它与业务对象相关,但内容是通用的。
感谢大家的时间。

4

2 回答 2

2

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

免责声明:这是一个非答案的答案,因为它既是答案又是问题。可能应该是评论,但除非您提出/回答问题,否则您无法发表评论,但既然我真的想提供帮助,我会尽我所能,即使这不是这里的做法。所以起诉我。

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

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

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

在 JOIN 语法问题上,使用 JOIN...ON 子句比 WHERE 子句更可取,因为它将实体与数据过滤操作结合起来需要做的事情分开。

于 2012-12-30T02:30:47.723 回答
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 中的嵌套循环连接密切相关。您可以将此称为连接条件中的循环。

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

FROM A cross join B

比:

FROM A, B

其次,如果你把“,”去掉,你仍然有有效的语法:

FROM A B

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

第三个原因是最重要的原因。旧语法没有表达left outer join,right outer join和的方法full outer join

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

于 2012-12-29T15:03:24.523 回答