2013-07-23 5 views
0

J'ai une procédure stockée comme ceci:écriture procédure stockée dans l'autre procédure stockée

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 

dans ce eteint ma moyenne montre en quelques minutes, je veux montrer moyenne en HH: MM (heure, minutes), donc je l'ai écrit comme procédure stockée distincte pour obtenir la moyenne en heures et minutes, cette procédure stockée est comme ceci:

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 

ici am sortir mettre comme ceci: avearge 29: 6. Je veux montrer ces valeurs moyennes dans ma première procédure stockée ... comment puis-je écrire cette procédure stockée dans la procédure du premier magasin, ou est-ce tout autre moyen d'obtenir cette valeur moyenne? dans la première procédure stockée

+0

Utilisez un [FONCTION] (http://msdn.microsoft.com/en-us/library/ms186755.aspx) au lieu d'une procédure de 'test' – bummi

+0

comment je peux faire that.I suis nouveau en procédure stockée – user2603688

Répondre

1

vous pouvez cahnge votre procédure à une fonction comme celui-ci

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 

Et comme l'utilisation ist

....  
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

Merci beaucoup monsieur ,, cela fonctionne très bien – user2603688

0

Si vous regardez cette ligne de code:

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

... vous ne pensez pas que si vous envelopper avec un autre appel de fonction, il deviendra plus laid et illisible?

Vous pourriez écrire ceci un peu différemment. Voyons voir.

Étape 1 - extraire le calcul timespan dans une expression séparée

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 
    ... 

Cette façon dont vos minutes sont toujours disponibles pour le reste de la requête si vous en avez besoin.

Étape 2 - retirer CONVERT pour AVG()

Il est plus facile à lire pour le convertir comme ceci:

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 
    ... 

Il est évident que votre AVG() doit calculer avec précision, et de cette façon vous n ne perdez aucune précision.

Étape 3 - oublier la procédure/fonction

Si vous n'avez pas besoin de la conversion à HH: MM nulle part ailleurs dans votre code, mais ici, ne crée pas de fonctions pour éviter de polluer votre schéma. Si vous utilisez SQL Server 2008 ou version ultérieure, le type TIME peut vous aider.

algorithme pour obtenir vos minutes HH: MM yould être:

  • obtenir vos minutes DATETIME ('1900-01-01 HH: MI: SS') en utilisant DATEADD(MI, Average, 0)
  • obtenir TIME (» HH: MI: SS ') de cette chose laide, en utilisant CAST (DATEADD (MI, Moyenne, 0) que le temps)
  • obtenir GAUCHE (CAST (DATEADD (MI, Moyenne, 0) comme TIME), 5)

Pour montrer ce que je veux dire, voici le code:

;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