2013-07-23 5 views
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 

в этом из положить мой средний показывает в минутах, я хочу, чтобы показать среднюю в ЧЧ: ММ (часы, минуты), так что я написал в виде отдельной хранимой процедуры для получения среднего в часах и минутах, что хранимая процедура выглядит так:

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. insted получения среднего значения в первой хранимой процедуре. Я хочу показать эти средние значения в моей первой хранимой процедуре. Так как я могу записать этот хранимый процедурный код в первой процедуре хранилища, или это любой другой способ получить это среднее значение в первой хранимой процедуры

+0

Используйте [FUNCTION] (http://msdn.microsoft.com/en-us/library/ms186755.aspx) вместо процедуры 'test' – bummi

+0

, как я могу сделать that.I новичок в хранимом процедуре – user2603688

ответ

1

вы можете cahnge вашу процедуру к функции, как этот

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

Большое спасибо sir, это отлично работает – user2603688

0

Если посмотреть на эту строку кода:

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

... вам не кажется, что если вы завернете другим вызовом функции, он станет более уродливым и нечитаемым?

Вы можете написать это несколько иначе. Посмотрим.

Шаг 1 - извлечь расчет TimeSpan в отдельном выражении

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 для 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 yould быть:

  • получить ваши минут DATETIME ('1900-01-01 HH: MI: SS') с помощью DATEADD(MI, Average, 0)
  • получить TIME (» HH: MI: SS ') из этой уродливой вещи, используя CAST (DATEADD (MI, Average, 0) как TIME)
  • получить 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 
Смежные вопросы