首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >我应该避免联接中的循环吗?

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

Stack Overflow用户
提问于 2012-12-29 14:27:11
回答 2查看 950关注 0票数 4

我记得有人教我使用,在使用sql连接表时,不要创建循环。实际上,使用Business,它甚至告诉我我在宇宙中定义的模式中是否有循环。

我试着在网上搜索这份声明,但没有找到任何参考资料。

为什么这么做很危险?

编辑:也许我太简单了。

我的问题不是关于作为"FOR循环“或类似循环的循环。我说的是SELECT语句中的WHERE子句:

代码语言:javascript
运行
复制
WHERE TABLE1.foo = TABLE2.foo
  AND TABLE2.bar = TABLE3.bar
  AND TABLE3.baz = TABLE1.baz

如果您绘制该关系,您将在联接中看到"a循环“。从正确性和/或性能的角度来看,这是否危险?

多亏了所有人。

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

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

代码语言:javascript
运行
复制
------------          -----------------      ----------------------
- 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_TABLE中,我们有处理传递的每个日期的列表。所以,几天内就可以准备好送货。
  • 在最后一张表中,我们有每一次交货的详细情况。因此,在本表中,我们将跟踪与交付准备有关的每一个事件。

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

连接非常简单:

代码语言:javascript
运行
复制
DELIVERY.id = DELIVERY_DATE.delivery_id AND 
DELIVERY_DATE.id = DELIVERY_DETAILS.date_id  

现在,假设我想加入另一个表,在这个表中,我有一些关于某个日期的传递的其他信息。让我们来定义它:

代码语言:javascript
运行
复制
------------  
- EMPLOYEE -
------------
- company  -
- year     -
- number   -
- date     -
- employee -
------------

现在的加入应该是:

代码语言:javascript
运行
复制
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  

总之,我将结束让员工同时加入交付和DELIVERY_DATE,在联接中有一个循环。

我应该用这种方式重写吗?

代码语言:javascript
运行
复制
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:最终找到一个链接

和往常一样,当你放弃寻找一个链接时,你会发现它。

所以,这篇文章解释了一切。它与业务对象相关,但内容是通用的。

感谢你的时间。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-12-30 02:30:47

编辑:我从更新中看到,这是BO设计器特有的一个问题,其中一个表不止一次使用,但是BO会自动组合联接子句,然后这些子句会错误地(或者说是无意地)限制结果集。这个问题实际上与循环无关,本质上,它实际上是关于在同一个查询中使用多个上下文中的实体。我将在下面留下我最初的答案,尽管它并没有真正解决OP的问题。

免责声明:这是一个不回答的问题,因为它既是一个答案,也是一个问题。这可能是一个评论,但你不能评论,除非你问/回答问题,但由于我真的想帮助,我会尽我所能的唯一方式,即使事情不是这样做在这里。那就告我。

简单来说,答案是否定的,您不应该避免联接中的循环(或“循环”)。

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

在您的示例中,为什么员工在交付表中扮演角色?你为什么要加入那些专栏?这意味着,员工的“日期”与送货日期相同?我理解这是一个人为的例子,但我想指出的一点是,联接是否在图中创建循环完全(主要)取决于特定结果集的逻辑意义。

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

票数 2
EN

Stack Overflow用户

发布于 2012-12-29 15:03:24

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

代码语言:javascript
运行
复制
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子句中的",“意为”交叉连接“。在大多数情况下,这是一个非常昂贵的手术。更好的办法是明确你想要完成的事情:

代码语言:javascript
运行
复制
FROM A cross join B

它的意图比以下更清楚:

代码语言:javascript
运行
复制
FROM A, B

其次,如果您离开了",“out,则仍然有有效的语法:

代码语言:javascript
运行
复制
FROM A B

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

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

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

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/14082580

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档