0

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

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

这里我出来了 像这样:平均 29:6。在第一个存储过程中获取平均值..我想在我的第一个存储过程中显示这个平均值..那么我如何在第一个存储过程中编写这个存储过程,或者有没有其他方法来获得这个平均值在第一个存储过程中

4

2 回答 2

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

并使用 ist like

 ....    
 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
 ....
于 2013-07-23T06:32:47.777 回答
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 的算法是:

  • 让你的分钟到 DATETIME ('1900-01-01 HH:MI:SS') 使用DATEADD(MI, Average, 0)
  • 使用 CAST(DATEADD(MI, Average, 0) as TIME) 从这个丑陋的东西中获取 TIME ('HH:MI:SS')
  • 得到 LEFT(CAST(DATEADD(MI, Average, 0) as 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
于 2013-07-23T08:35:50.967 回答