重复操作与多级查询

时间:2014-08-20 10:20:46

标签: sql sql-server

我总是被我应该如何处理这些问题所困扰,哪种解决方案更好。我想示例代码应该更好地解释它。

假设我们有一个包含3列的表:

  • (int)的标识
  • (nvarchar的)名称
  • (int)的值

我想在Value列上获取基本列和一些计算,但每个计算都基于前一个,换句话说就是这样:

SELECT
    *,
    Value + 10 AS NewValue1,
    Value / NewValue1 AS SomeOtherValue,
    (Value + NewValue1 + SomeOtherValue) / 10 AS YetAnotherValue
FROM
    MyTable
WHERE
    Name LIKE "A%"

显然这不起作用。 NewValue1SomeOtherValueYetAnotherValue在查询中处于同一级别,因此他们无法在计算中互相引用。

我知道有两种方法可以编写能够提供所需结果的查询。第一个涉及重复计算。

SELECT
    *,
    Value + 10 AS NewValue1,
    Value / (Value + 10) AS SomeOtherValue,
    (Value + (Value + 10) + (Value / (Value + 10))) / 10 AS YetAnotherValue
FROM
    MyTable
WHERE
    Name LIKE "A%"

另一个涉及构建这样的多级查询:

SELECT
    t2.*,
    (t2.Value + t2.NewValue1 + t2.SomeOtherValue) / 10 AS YetAnotherValue
FROM
(
    SELECT
        t1.*,
        t1.Value / t1.NewValue1 AS SomeOtherValue
    FROM
    (
        SELECT
            *,
            Value + 10 AS NewValue1
        FROM
            MyTable
        WHERE
            Name LIKE "A%"
    ) t1
) t2

但哪一种是解决问题的正确方法,还是只是“更好”?

P.S。是的,我知道“更好”甚至“好”的解决方案在SQL中并不总是相同的,并且取决于很多因素。

2 个答案:

答案 0 :(得分:1)

我已经厌倦了两种变体中的许多不同的计算组合。它们总是生成相同的执行计划,因此可以假设性能方面没有差异。从代码可用性的角度来看,第一种方法显然更好,因为代码更具可读性和紧凑性。

答案 1 :(得分:1)

没有"对"写这种查询的方法。与大多数数据库一样,SQL Server(MySQL是一个值得注意的例外)不会为每个子查询创建中间表。相反,它会优化整个查询,并经常将表达式的所有计算移动到单个处理节点中。

无法在同一级别重复使用列别名的原因是ANSI标准定义。特别是,标准中没有任何内容指定单个表达式的评估顺序。在不知道顺序的情况下,SQL无法保证在评估之前定义变量。

我经常编写多级查询 - 使用子查询或CTE - 使查询更具可读性和可维护性。但话又说回来,我也会将逻辑从一个变量复制到另一个变量,因为它是有利的。在我看来,这是查询的作者需要决定的事情,考虑到查询是否是需要维护的系统的代码的一部分,本地编码标准,查询是否可能被修改和类似的考虑。