这个问题是在朋友发表评论之后发出的。他说,当一个查询有很多子查询时,这是一个信号,表明数据库存在设计缺陷,必须避免这些缺陷。他还说许多书都有同样的建议。
我同意部分内容,但我认为这些查询具有复杂的逻辑,需要大量子查询,或者,为了避免子查询,查询的物化视图或大量数据冗余。
那么,子查询的真相是什么?他们必须始终避免吗?没问题吗?他们是否表明数据库设计存在缺陷?是否有可能使数据库设计允许复杂查询而不会产生数据冗余?
答案 0 :(得分:5)
不,子查询的存在并不一定意味着数据库模式的设计很差。
应谨慎使用Correlated subqueries(即内部条件指外部条款时)。
除此之外,子查询通常是解决问题的有用且自然的方式。在可能的情况下,我倾向于使用连接而不是子查询。
许多查询优化器会将某些类型的子查询转换为连接。
答案 1 :(得分:3)
你朋友的逻辑是有缺陷的。
尽管SQL及其各种实现基于某种松散的关系模型,但它缺少许多基本relation operators的关键字或缩写,特别是半连接,半差异(a.k.a.反连接)和除法。我经常使用子查询在SQL代码中编写半连接和半连接;至于除法,我不确定是否可以在不使用子查询的情况下在单个查询中执行!
所以我对子查询的使用取决于SQL语言的可疑设计,而不是我正在使用的数据库的设计。
P.S。我想知道您和/或您的朋友是否使用术语“数据库”来表示数据库(数据集合)和DBMS(管理数据的软件系统)可互换。如果是这样,并且在上下文中你的意思是DBMS,那么语句“当一个查询有很多子查询时,它是'闻到',DBMS有设计缺陷”可能确实如此。
答案 2 :(得分:1)
我倾向于同意你的朋友,如果你经常需要子查询,这表明数据库的组织方式不容易查询。它对于规范化规则可能是完美的,但对于关于数据的常见问题则不方便。如果是这样,解决方案通常会创建一个视图或中间表,以更可搜索的方式将数据汇集在一起。
我同意Mitch Wheat的观点,即子查询经常有用。关于它们有用性的问题与如何最好地组织数据以使其易于查询的问题是正交的。
答案 3 :(得分:1)
“相关子查询”(即,where条件依赖于从包含查询的行获得的值)将对每行执行一次。非相关子查询(where条件独立于包含查询的子查询)将在开头执行一次。 SQL引擎自动进行区分。
子查询可能正在执行“全表扫描”。换句话说,不使用索引并返回太多行,而主查询中的Where需要过滤掉。
通常它是优化器无法确定子查询可以作为连接执行的结果,在这种情况下,它会为表中的每个记录执行子查询,而不是将子查询中的表连接到表中正在查询。一些更“企业化”的数据库在这方面做得更好,但有时它们仍然会错过它。
因此,更喜欢在子查询上加入以更快地获得结果并确保结果。