我有一个这样的存储过程:
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。试图在第一个存储过程中获得平均值..我想在我的第一个存储过程中显示这个平均值。所以我如何在第一个存储过程中编写这个存储过程,或者以其他任何方式获得这个平均值在第一个存储过程
答案 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)
为了证明我的意思,这是代码:
;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