【问题标题】:How do I programmatically create JOIN statements?如何以编程方式创建 JOIN 语句?
【发布时间】:2011-07-14 16:36:24
【问题描述】:

技术:VS.net 2008、C#、Winforms、SQL Server 2008

我目前正在为工作编写一个可视化选择查询构建器,但我对如何创建连接感到困惑。当我手动编写它们时,我了解我需要如何执行它们,但我不确定如何将其转换为算法。

目前,我的选择查询构建器具有获取表、显示列、选择所需列、在特定列上使用“AND、OR”语句的所有功能,并且它可以正常运行查询。但是一旦涉及到另一张桌子,所有的地狱都会崩溃。

使用已经存在的应用程序是不可能的,并且建议其他产品应该被否决的答案。

是否有一条硬性规定:“在编写 Join 语句时,您应该执行 __ 和 __ 等...)

我最初的概念是基于 MS Access,我注意到它使用所有左连接,但我不明白为什么会这样。

【问题讨论】:

  • 也许我没有得到您的问题,但是:在编写连接语句时,您应该选择所需的表、要在连接中使用的列以及您使用的连接类型。没有更多的了。
  • MS Access 不使用“所有左连接”。
  • 硬性规则将在 SQL 语法中说明。比如this
  • 这个问题不太直接,但sqlkata.vivida-apps.com/docs/join之类的内容可能会对您有所帮助

标签: c# .net sql sql-server-2008


【解决方案1】:

您想知道的基本标准:

  • 哪些字段使表格相关联?
  • 哪些字段不等价?
  • 您想将结果数量限制为仅匹配,还是包括不匹配?

第一个条件对于您的ON 语句很重要。第二个也是如此。在查询中,您希望查看某些字段共有但其他字段没有的结果,这种情况并不少见,例如:

SELECT a.LineId, a.Total, b.Subtotal
FROM TableA as A
INNER JOIN TableB as B
    ON b.subtotal = a.total
    AND b.ID <> a.LineId

第三个标准是您如何知道您需要LEFT 还是INNER JOIN

如果您只想查看匹配的行,请使用INNER。如果您想查看第一个表中的所有行,但在第二个表存在时显示匹配项,请使用LEFT JOIN

您可能还需要考虑 FULL OUTER 连接,它显示两个表的所有结果。 CROSS JOINs 没有被广泛使用,因此您需要确定是否有这些用例。它们显示笛卡尔积(即 tableA 中的所有行与 TableB 中的所有行匹配 - 所有可能的组合)。

你能更具体地说明你需要什么吗?

【讨论】:

    【解决方案2】:

    这类事情没有“硬性规定”,因为它在很大程度上取决于数据的结构。我认为您在观察 MS Access 如何处理它方面有了一个良好的开端。其他好的选择是在设计器中创建一些示例实体框架或 LINQ 2 SQL 模型,并观察它们是如何在后端转换为 SQL 的。 (尤其是 EF 的连接设计器非常聪明和灵活)。

    Access 主要使用左连接,因为在对源数据结构的了解绝对为零的情况下,它们是“最安全的”。诀窍是尝试设计一个符合用户期望的工具。在 Access 的查询设计器中,如果我选择一个表,然后将其连接到另一个表,最可能的情况是“我想要这个表中的所有数据,但我也需要从另一个表中提取数据”,这是一个左加入。如果产生了内部连接,但我最终没有取回第一个表中的所有行,那可能会令人惊讶。

    当然,如果您确实需要,Access 还允许您修复这些规则。这是最好的方法:生成一个合理的默认值,最不可能让您的用户感到困惑,然后在他们知道的情况下为他们提供更改默认值的方法。

    一种选择是将连接语言翻译成更高级别的语言;例如,如果您的用户完全熟悉数据建模,他们可能会识别“一对多”(内部联接)与“一对零或多”(外部联接)。甚至可能使在构建器中创建连接的操作使用完全不同的词,例如“可选链接”与“必需链接”,甚至“连接查找表”与“合并子数据”。找出您的用户在使用您的查询设计器时在他们脑海中的想法,将它们映射到适当的 JOIN 类型并使用它们。同样,EF 设计者已将连接的 SQL 概念映射到运行良好的父/子关系的更高级别数据建模概念。

    从技术角度来看,我有一些关于编写 JOIN 的个人规则。其中一些基于可能已经过时或过时的关于如何优化查询和索引的想法,可能不再严格需要,但对我很有帮助:

    • 始终使用长格式连接语法(无 WHERE 子句快捷方式
    • 尽可能将子表行的所有条件放入 ON 子句(也就是说,我的 WHERE 子句很少有条件包含内连接表中的字段)
    • 在已知安全的地方使用 INNER JOIN
    • 尽可能使用 LEFT JOINS 和 IS NOT NULL 来代替子查询。

    编辑:我已经纠正了我认为 JOINS 比子查询执行得更快的错误看法。 (当然,无论如何你都会进行自己的性能测试,对吧?:))

    【讨论】:

    • 仅供参考,在 SQL Server 2005+ 中,INEXISTS 的子查询通常比 LEFT JOIN...(NOT) NULL 执行得更好
    • 我承认自从 MSDE 流行以来,我实际上并没有对差异进行基准测试。感谢您的提醒。
    • 没问题。 Gail Shaw 不久前写了一篇很棒的博文:sqlinthewild.co.za/index.php/2010/03/23/…
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-03-10
    • 2013-11-15
    • 2013-12-28
    • 2011-02-10
    • 2011-04-02
    • 2012-02-26
    • 2011-03-01
    相关资源
    最近更新 更多