Sql 重复操作与多级查询
我总是为我应该如何处理这些问题而烦恼,哪种解决方案更好。我想示例代码应该更好地解释它 假设我们有一个包含3列的表:Sql 重复操作与多级查询,sql,sql-server,Sql,Sql Server,我总是为我应该如何处理这些问题而烦恼,哪种解决方案更好。我想示例代码应该更好地解释它 假设我们有一个包含3列的表: (int)Id (nvarchar)名称 (int)值 我想得到基本列加上值列上的一些计算,但每一个计算都是基于前一个,换句话说,类似这样: SELECT *, Value + 10 AS NewValue1, Value / NewValue1 AS SomeOtherValue, (Value + NewValue1 + SomeOtherV
- (int)Id
- (nvarchar)名称
- (int)值
值
列上的一些计算,但每一个计算都是基于前一个,换句话说,类似这样:
SELECT
*,
Value + 10 AS NewValue1,
Value / NewValue1 AS SomeOtherValue,
(Value + NewValue1 + SomeOtherValue) / 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
显然,这是行不通的NewValue1
、SomeOtherValue
和YetAnotherValue
在查询中处于同一级别,因此它们在计算中不能相互引用
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
*,
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
*,
Value + 10 AS NewValue1,
Value / NewValue1 AS SomeOtherValue,
(Value + NewValue1 + SomeOtherValue) / 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
但是,哪一种方法是解决问题的正确方法,还是仅仅是“更好”
是的,我知道“更好”甚至“好”的解决方案在SQL中并不总是一样的,这取决于许多因素。我已经厌倦了这两种变体中的许多不同计算组合。它们总是生成相同的执行计划,因此可以假设性能方面没有差异。从代码可用性的角度来看,第一种方法显然更好,因为代码更具可读性和紧凑性。编写此类查询没有“正确”的方法。与大多数数据库一样(MySQL是一个显著的例外),SQL Server不会为每个子查询创建中间表。相反,它将查询作为一个整体进行优化,并经常将表达式的所有计算移动到单个处理节点中 列别名不能在同一级别重复使用的原因在于ANSI标准定义。特别是,标准中没有任何内容指定单个表达式的求值顺序。如果不知道顺序,SQL无法保证在求值之前定义变量
我经常编写多级查询——使用子查询或CTE——以使查询更具可读性和可维护性。不过,我还要把逻辑从一个变量复制到另一个变量,因为这是权宜之计。在我看来,这是查询作者需要决定的事情,考虑到查询是否是需要维护的系统代码的一部分,本地编码标准,查询是否可能被修改,和类似的考虑。显然,第一种方法是更好的方法,因为它不需要通过子查询重新计算临时表。此外,这里有两个子查询,而第一个子查询没有。这是一个有趣的见解。检查执行计划是否有差异,如果没有,请坚持使用可读性更强的执行计划。我之所以接受这一点,是因为我提到了相同的执行计划。然而,应该注意的是,即使查询产生相同的执行计划,执行时间也可能以可重复的方式不同(即,一个查询总是比另一个查询执行得稍快)。这些差异通常很小,但如果查询真的很复杂,它可能会更明显。