1

我目前正在开展一个项目,该项目将在 MS SQL 数据库中存储有关我们客户的特定财务信息。之后,我们的用户需要能够查询数据库,以根据特定条件(例如,大于特定规模的客户端、特定地理位置的客户端)从客户端返回数据,并将其汇总以用作基准。我们的财务软件将使用脚本访问该数据库。

我目前正在为数据库编写存储过程。我打算做的是根据可以使用的不同类型的标准编写几个不同的存储过程。他们将返回客户编号。

我的实际问题是检索数据的方法。我需要对客户数据进行几种不同的计算。让不同的存储过程根据客户端编号进行计算并返回结果是更好的做法,还是让存储过程返回有关客户端的所有信息并在脚本中执行计算更好?

性能可能是一个问题,因为数据库中会有很多客户端,所以我希望该方法相当有效。

4

10 回答 10

3

有趣的是,数据仓库人员一直都在这样做。他们经常使用最简单的 SQL(SELECT SUM/COUNT...GROUP BY...),并在报告编写工具中完成数据库之外的工作。

我认为您应该获得一份 The Data Warehouse Toolkit 的副本,并看看如何以一种相当简单的方式完成这项工作。更灵活,可能更具可扩展性。

于 2008-10-06T16:52:31.013 回答
1

我认为这在很大程度上与所涉及的数据和您正在执行的操作有关。我通常发现,在进行减少从数据库(分组和聚合)返回的大小的计算时,在数据库中执行它会更有效。当您开始进行其他计算时,它并不那么明确。

于 2008-10-06T16:51:09.657 回答
1

在大多数情况下,就像我认为您所描述的那样,使用存储过程更有效,但是在某些极端情况下并非如此。最好的答案是尝试两种方法并进行一些负载测试以确定哪种方法最有效。

于 2008-10-06T16:52:24.740 回答
1

这真的取决于操作。很有可能将这些东西作为数据库中的计算列,在视图或 SP(或使用 UDF)中预先计算它们,在 ETL 或汇总阶段单独计算并存储它们,或者让客户来做。

我会避免让客户做任何事情,除非你知道你可以始终如一地控制计算,这样他们就不会犯错误(所有独立完成工作的报告作者都是灾难的根源),特别是如果计算规则可能改变。

于 2008-10-06T16:56:17.010 回答
0

SQL Server 是一个关系数据存储。我建议每次计算一个存储过程,它为客户端执行相同的计算。只需将ID作为参数传入即可获取客户端的具体结果。

“性能可能是一个问题,因为会有很多客户”......这取决于表的规范化和索引方式。除非您完全了解索引的真正含义,否则不要对每一列进行索引。

编辑〜查看您的计算。有些可以卸载到前端客户端。

于 2008-10-06T16:53:33.630 回答
0

从您的问题看来,最有效的方法是在 SP 中进行所有计算并将单个(?)结果返回到您的脚本。

如果您决定在脚本中进行处理,则应确保将检索到的数据限制在必要的范围内,并确保尽可能少地往返数据库。

于 2008-10-06T16:53:55.907 回答
0

如果确定计算结果的业务规则容易更改,请不要在存储过程中编写此类代码。更好的地方是控制器(MVC 中的 C)。这些规则将是可插入的并且易于更改。

同样从可扩展性的角度来看,复制应用服务器并不像复制数据库服务器那样昂贵。

这并不意味着不能使用存储过程。报告生成将是使用存储过程完成计算的理想候选者之一。

于 2008-10-06T17:11:20.820 回答
0

考虑是否需要数据仓库。为报告而优化的数据库与为数据输入而优化的数据库非常不同。

于 2008-10-06T19:17:11.733 回答
0

你所说的一切让我认为你应该考虑存储你的数据。如果您发现自己针对 OLTP 系统编写复杂的连接并需要额外的计算(听起来确实如此),那么对数据进行非规范化并将预先计算的聚合存储在仓库中将使您的生活变得更加简单。

尽管每个人似乎都想向您扔大量书籍和产品,但如果您的问题空间是离散的并且您的源数据管理良好,那么任务通常是微不足道的。

于 2008-10-07T14:11:41.617 回答
-1

您可以在存储过程中进行任何计算并返回数据。像存储过程这样的利息计算需要大量的计算。

您必须以任何方式使用其他表数据计算数据。

SUM我们可以在SP中做,

Declare @SUMAmount decimal(12,3) 

-- 还声明@A、@B 等

Select @SUMAmount= SUM(ISNULL(@A,0)+ISNULL(@B,0)+ISNULL(@C,0)+ISNULL(@D,0))

Select @SUMAmount= SUM((ISNULL(@A,0)+ISNULL(@B,0))*(ISNULL(@C,0)-ISNULL(@D,0)))

根据您的要求,您可以提供条件。

ISNULL 用于检查数据是否为 ​​NULL,然后返回 0。无法使用 Null 值进行计算,因此最好给出 ISNULL 条件。

Select A,B,SUM(C),D From TableName
Where SUM(C)>0
Group By A,B,D

这里有聚合函数和非聚合函数,所以你必须使用 Group By。您可以根据您的条件获取值,例如:“SUM(C)>0”。Group By 之后也可以在这里使用。

 Declare @TotalNoofDays  int
 @TotalNoofDays = DATEDIFF(d, fromdate, todate) 

用于查找使用此功能的天数。

您可以使用类似的条件,

if @DueAmount >=0
BEGIN
IF @DiscountFlag = 1
BEGIN
SET @DueIntAmount   = 0
END
ELSE
   BEGIN
     SET @DueIntAmount  = ((@DueAmount*(@IntRateOnDue/100))/365)*@NoofDays
   END
  SET @ExcessInterestAmount = 0
END
ELSE
BEGIN
SET @DueIntAmount   = 0
SET @ExcessInterestAmount = ((@DueAmount*(@IntRateOnDeposit/100))/365)*@NoofDays
 END

就像您可以在存储过程中进行的计算一样。

如果要对记录数一一进行计算,则可以使用临时表while循环..

 Create Proc NewLearningProcedure
 (
   @Name Varchar(50),
   @Date DateTime
 )
 AS
 Begin

Declare @Temp Table
(
   ID int Identity(1,1),
   Name Varchar(50),
   Date DateTime
)

Insert Into @Temp
Select @Name,@Date

Declare @i int
set @i=10

While @i>0
Begin
  Insert Into @Temp
  Select @Name+CAST(@i as varchar(50)),@Date

  Set @i=@i-1
 End


 Select * from @Temp


 End

就像您可以使用存储过程做任何事情一样。

于 2012-10-16T12:35:50.180 回答