在其他存储过程中写入存储过程

时间:2013-07-23 05:52:58

标签: sql-server stored-procedures

我有一个这样的存储过程:

ALTER PROCEDURE [dbo].[Performance] 

     @startdate NVARCHAR(100), 
     @enddate NVARCHAR(100)

AS
BEGIN
     SET NOCOUNT ON;

     SELECT
          l.LocName
         ,v.Vtype
         ,SUM(DATEDIFF(MI, t.Paydate, t.DelDate)) AS TotalDiff
         ,CONVERT(DECIMAL(10, 1), AVG(CONVERT(NUMERIC(18, 2), DATEDIFF(MI, t.Paydate, t.DelDate)))) AS Average
     FROM Transaction_tbl t
     LEFT JOIN VType_tbl v ON t.vtid = v.vtid
     LEFT JOIN Location_tbl l ON t.Locid = l.Locid
     WHERE t.Locid IN
          (
               SELECT t1.Locid
               FROM Transaction_tbl t1
          )
          AND dtime BETWEEN '' + @startdate + '' AND '' + @enddate + ''
          AND status >= 5
     GROUP BY
          v.Vtype
         ,l.LocName
         ,l.Locid
     ORDER BY l.Locid

END

LocName             Vtype       TotalDiff   Average

Fashion Avenue     VIP           84          2.1
Fashion Avenue     Normal        14007       200.1
Address Hotel    Normal          33169        1745.7

在这个输出我的平均值显示在几分钟,我想显示HH:MM(小时,分钟)的平均值,所以我写作单独的存储过程获得平均小时和分钟,该存储过程是这样的:

ALTER PROCEDURE [dbo].[test] @locid INT
AS
BEGIN
     DECLARE
          @Mns DECIMAL
         ,@dec DECIMAL

     SELECT @dec = AVG(CONVERT(NUMERIC(18, 2), DATEDIFF(MI, t.Paydate, t.DelDate)))
     FROM Transaction_tbl t
     WHERE Locid = @locid;

     SELECT @Mns = @dec % 60;

     SELECT Avearge = 
            CONVERT(VARCHAR(10), (CONVERT(DECIMAL(10), @dec / 60))) + ':'
          + CONVERT(VARCHAR, @Mns)

END

这里出去就像这样: Avearge 29:6。试图在第一个存储过程中获得平均值..我想在我的第一个存储过程中显示这个平均值。所以我如何在第一个存储过程中编写这个存储过程,或者以其他任何方式获得这个平均值在第一个存储过程

2 个答案:

答案 0 :(得分:1)

您可以将过程更改为此类函数

Create FUNCTION [dbo].[test] (@dec NUMERIC(18, 2)) RETURNS Varchar(50) 
AS
BEGIN
     DECLARE
          @Mns DECIMAL

     DECLARE @Average  Varchar(50) 

     SELECT @Mns = @dec % 60;

     SELECT @Average = 
            CONVERT(VARCHAR(10), (CONVERT(DECIMAL(10), @dec / 60))) + ':'
          + CONVERT(VARCHAR, @Mns)
     RETURN @Average     

END

并像

一样使用它
 ....    
 SELECT
      l.LocName
     ,v.Vtype
     ,SUM(DATEDIFF(MI, t.Paydate, t.DelDate)) AS TotalDiff
     ,[dbo].[test](
     CONVERT(DECIMAL(10, 1), AVG(CONVERT(NUMERIC(18, 2), DATEDIFF(MI, t.Paydate, t.DelDate))))
     ) AS Average
 FROM Transaction_tbl t
 ....

答案 1 :(得分:0)

如果你看一下这行代码:

CONVERT(DECIMAL(10, 1), AVG(CONVERT(NUMERIC(18, 2), DATEDIFF(MI, t.Paydate, t.DelDate)))) AS Average

...难道你不认为如果你用另一个函数调用它会变得更难看和不可读吗?

你可以用不同的方式写这个。我们来看看。

第1步 - 在单独的表达式中提取时间跨度计算

SELECT
  ...,
  CONVERT(DECIMAL(10, 1), AVG(CONVERT(NUMERIC(18, 2), datecalc.val))) AS Average
FROM 
  Transaction_tbl t
  CROSS APPLY(
    SELECT val = DATEDIFF(MI, t.Paydate, t.DelDate)
  ) datecalc
  ...

这样,如果您需要,您的分钟始终可用于查询的其余部分。

第2步 - 删除CONVERT for AVG()

将它转换为更具可读性:

SELECT
  ...,
  CONVERT(DECIMAL(10, 1), AVG(datecalc.val * 1.0)) AS Average
FROM 
  Transaction_tbl t
  CROSS APPLY(
    SELECT val = DATEDIFF(MI, t.Paydate, t.DelDate)
  ) datecalc
  ...

显然你的AVG()必须精确计算,这样你就不会失去任何精度。

第3步 - 忘记程序/功能

如果您不需要在代码中的任何其他位置转换为HH:MM,请在此处创建任何函数以避免污染您的架构。如果您使用SQL Server 2008或更高版本,TIME类型可以帮助您。

让你的分钟到HH的算法:MM你可以:

  • 使用DATEADD(MI, Average, 0)
  • 将您的会议记录转到DATETIME('1900-01-01 HH:MI:SS')
  • 从这个丑陋的东西中获取TIME('HH:MI:SS'),使用CAST(DATEADD(MI,Average,0)作为TIME)
  • 获得LEFT(CAST(DATEADD(MI,平均值,0)为TIME),5)

为了证明我的意思,这是代码:

;WITH orig AS (
    SELECT id = 1, dt = CAST('2013-07-23 09:01' as datetime), dt2 = CAST('2013-07-23 09:00' as datetime)
    UNION ALL SELECT id = 1, '2013-07-24 01:00', '2013-07-23 12:00'
    UNION ALL SELECT id = 2, '2013-07-23 10:15', '2013-07-23 10:07'
    UNION ALL SELECT id = 2, '2013-07-23 09:10', '2013-07-23 08:00') -- STEP#0: data sample
,avgs AS (
    SELECT
      id,
      val = avg(val1 * 1.0) -- STEP#2: calculating average timespan in minutes
    FROM orig
    CROSS APPLY(
      SELECT val1 = DATEDIFF(MI, dt2, dt) -- STEP#1: calculating timespan in minutes
    ) spancalc
    GROUP BY id)
SELECT
  id,
  str = LEFT(val2, 5) -- STEP#4: getting 'HH:MI' string output
FROM 
  avgs
  CROSS APPLY(
    SELECT 
      val2 = CAST(DATEADD(MI, val, 0) as TIME) -- STEP#3: getting average timespan to TIME format
  ) timecalc