6

当我编写 SQL 查询时,我发现自己经常在想“没有办法用单个查询来做到这一点”。发生这种情况时,我经常求助于使用临时表(一种或另一种)的存储过程或多语句表值函数,最终只是简单地组合结果并返回结果表。

我想知道是否有人知道,仅从理论上讲,是否应该编写任何将单个结果集作为单个查询(而不是多个语句)返回的查询。显然,我忽略了代码可读性和可维护性等相关点,甚至可能是查询性能/效率。这更多是关于理论 - 可以做到......别担心,我当然不打算在多语句在所有情况下更适合我的目的时开始强迫自己编写单语句查询,但是对于是否有可行的方法从单个查询中获取结果,这可能会让我三思而后行。

我想一些参数是有序的 - 我正在考虑一个关系数据库(例如 MS SQL),其表遵循常见的最佳实践(例如所有表都有一个主键等)。

注意:为了赢得“接受的答案”,您需要提供明确的证明(参考网络材料或类似的东西。)

4

5 回答 5

3

我相信这是可能的。我处理过非常困难的查询、非常长的查询,而且通常可以使用单个查询来完成。但大多数时候,它更难维护,所以如果你用一个查询来做,请确保你仔细地评论你的查询。

我从未遇到过无法在单个查询中完成的事情。
但有时最好在多个查询中执行此操作。

于 2010-01-06T18:42:59.697 回答
2

我无法证明这一点,但我相信答案是谨慎的,只要您的数据库设计正确完成。通常被迫编写多个语句以获得特定结果表明您的架构可能需要一些改进。

于 2010-01-06T18:43:09.603 回答
2

我会说“是”,但无法证明。但是,我的主要思考过程:

  • 任何选择都应该是基于集合的操作

  • 您的假设是您正在处理数学上正确的集合(即正确归一化)

  • 集合论应该保证它是可能的

其他想法:

  • 多个 SELECT 语句经常加载临时表/表变量。这些可以在 CTE 中派生或分离。

  • 任何 RBAR 处理(无论好坏)现在都通过 CROSS/OUTER APPLY 处理到派生表上

  • 在这种情况下,我认为 UDF 将被归类为“作弊”,因为它允许您将 SELECT 放入另一个模块而不是单个模块

  • DML 的“之前”序列中不允许写入:这会将状态从 SELECT 更改为 SELECT

  • 您在我们的商店中看到了一些代码吗?

编辑,词汇表

编辑:申请:作弊?

SELECT
    *
FROM
    MyTable1 t1
    CROSS APPLY
    (
        SELECT * FROM MyTable2 t2
        WHERE t1.something = t2.something
    ) t2
于 2010-01-06T18:51:11.840 回答
2

至少使用最新版本的 Oracle 是绝对可能的。它有一个“模型子句”,使 sql 图灵完整。(http://blog.schauderhaft.de/2009/06/18/building-a-turing-engine-in-oracle-sql-using-the-model-clause/)。当然,这一切都具有通常的限制,即我们并没有真正的无限时间和记忆。

对于没有这些厌恶的普通 sql 方言,我认为这是不可能的。

我看不到如何在“普通 sql”中实现的任务是:假设一个表有一个整数类型的列

对于每一行“获取当前行的值并返回那么多行,获取该值,返回那么多行,然后继续,直到连续两次获取相同的值并将其作为结果返回。”

于 2010-01-06T18:52:34.490 回答
1

理论上是的,如果您使用函数或 OUTER APPLY 或子查询的曲折迷宫;但是,为了可读性和性能,我们总是最终使用临时表和多语句存储过程。

正如上面有人评论的那样,这通常表明您的数据结构开始变味了;并不是说这很糟糕,但也许是时候出于性能原因进行非规范化(我们中最好的人会发生),或者可能在规范化的“真实”数据前面放置一个非规范化的查询层。

于 2010-01-06T19:20:30.907 回答