【问题标题】:What is the most efficient way to process rows in a table?处理表中的行的最有效方法是什么?
【发布时间】:2015-05-12 03:10:48
【问题描述】:

我正在为我正在从事的项目自学基本和中级 SQL 概念。

我有很多数据需要进行处理,以便以不同的方式呈现。现在,我在 select 语句中使用标量函数调用来处理数据。

一个简单的例子,假设我的表中有一个名为 fun 的属性作为数据类型 int。我想处理我的表,以便所有 fun 10 的行都是“faa”。

所以我写了一个类似的 SQL 函数

CREATE FUNCTION dbo.fooORfaa
(
    @fun AS int
)
RETURNS VARCHAR(3)
AS
BEGIN
     IF (@fun < 10)
         RETURN 'foo'
     RETURN 'faa' 
END

然后我在类似这样的 select 语句中使用我的函数

select dbo.fooORfaa([mytable].[fun]) AS 'blah'
from mytable

这个例子很简单,但在我的真实代码中,我需要对一个或多个列执行一些相当复杂的逻辑,我正在从过程中选择子结果并将表连接在一起以及您需要在数据库中做的其他事情。

我必须在合理的时间跨度内处理大量记录。这种方法是解决这个问题的有效方法吗?我应该使用另一种技术吗?

【问题讨论】:

  • 如果您的 fooORfaa 函数底层的字段相对不变,和/或您正在进行的计算是“繁重”或“昂贵”,那么您最好将它们保存在额外的字段,这样您就不会在每次使用表格时浪费大量的 CPU 重做所有计算。一些适当的触发器可以在(希望)极少数情况下(希望)值确实发生更改,从而使表保持最新。
  • 使用 store 存储过程
  • 虽然不直观,但表值函数通常比标量值函数更有效。

标签: sql sql-server


【解决方案1】:

对于这个用例,您需要一个 CASE 构造。

SELECT
  CASE
    WHEN T.fun < 10 THEN 'foo'
    ELSE 'faa'
  END foo_faa
FROM
  myTable T

始终尝试使用基于集合的操作。用户定义的函数(大部分)会影响你的表现,应该是最后的手段。

See: CASE (Transact-SQL)

【讨论】:

  • 谢谢,我想我可以将它应用到我的大部分转换中。还有一个问题,如何防止我的选择语句爆炸?标量函数的一个很好的副作用是代码更具可读性。我可以使用存储过程嵌套一堆选择语句,但我认为这也可能对性能产生不利影响。
  • 你真的不能。没有免费的午餐。有时,您可以将一些东西放在一个视图中,但最终您会得到一个引用视图的意大利面条式视图,并且查询优化器在尝试将视图折叠在一起时很难制定有效的计划。因此,与 SQL 共存就是与此共存。这不像 c# 或其他过程语言。许多 SQL 方言具有过程扩展,例如 UDF,但这些通常保留用于边缘情况或事务性应用程序。像你正在做的检索几乎总是最好这样。
  • 谢谢。我想我只会对我的压痕非常挑剔。非常感谢。
  • 优秀。缩进很快就会成为第二天性。我无法忍受用三行难以理解的小写代码编写的巨大存储过程。它是不可维护的,即使是原作者,更不可读。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-23
  • 2015-02-14
  • 1970-01-01
  • 2011-07-13
  • 2010-11-27
  • 2014-01-27
相关资源
最近更新 更多