如何在存储的函数内运行2个查询

时间:2014-12-29 17:12:29

标签: sql sql-server function sql-function

我是SQL中的函数的新手,我希望得到一些指导。我在SQL中有一个函数,我想添加另一个查询,但我无法弄清楚如何实现它。

我目前的职能是:

ALTER FUNCTION dbo.CountVisits
(@startdate Datetime,
 @enddate Datetime,
)
RETURNS TABLE
AS
   RETURN       
       SELECT     
          COUNT(DISTINCT Invoice_Number) AS TotalVisits
       FROM         
          Invoice_Tb
       WHERE 
          dtcreated >= @startdate 
          AND dtcreated <= @enddate 
          AND Service_Id = '1'

当前输出:

Total Visits
------------
    15

这将返回服务ID为1的“TotalVisists”。现在,假设我还要包含“总访问次数”,我知道我可以在查询中执行两次查询。但有没有办法在函数中打破这个以运行另一个查询,并将它们作为输出的一部分放在一起?

我的第二个问题是:

 SELECT     
     COUNT(DISTINCT Invoice_Number) AS TotalVisitsALL
 FROM
     Daily_TB
 WHERE
     dtcreated >= @startdate 
     AND dtcreated <= @enddate 

我想要的输出:

Total Visits     TotalVisitsALL
--------------------------------
     15                300

2 个答案:

答案 0 :(得分:1)

在内联表值函数中使用两个查询:

ALTER FUNCTION dbo.CountVisits
(@startdate Datetime,
 @enddate Datetime,
)
RETURNS TABLE
AS
  RETURN
    SELECT
      (SELECT     
         COUNT(DISTINCT Invoice_Number) AS TotalVisits
       FROM         
         Invoice_Tb
       WHERE 
         dtcreated >= @startdate 
         AND dtcreated <= @enddate 
         AND Service_Id = '1') AS TotalVisits,
      (SELECT     
         COUNT(DISTINCT Invoice_Number) AS TotalVisitsALL
       FROM
         Daily_TB
       WHERE
         dtcreated >= @startdate 
         AND dtcreated <= @enddate) AS TotalVisitsALL

使用多语句表值函数:

ALTER FUNCTION dbo.CountVisits
(@startdate Datetime,
 @enddate Datetime,
)
RETURNS @tvData TABLE (TotalVisits INT, TotalVisitsALL INT)
AS
BEGIN
  DECLARE @TotalVisits INT, @TotalVisitsALL INT;

  SELECT
    @TotalVisits = COUNT(DISTINCT Invoice_Number)
  FROM         
    Invoice_Tb
  WHERE 
    dtcreated >= @startdate 
    AND dtcreated <= @enddate 
    AND Service_Id = '1';

  SELECT     
    @TotalVisitsALL = COUNT(DISTINCT Invoice_Number)
  FROM
    Daily_TB
  WHERE
    dtcreated >= @startdate 
    AND dtcreated <= @enddate;

  INSERT INTO @tvData(TotalVisits,TotalVisitsALL)
  VALUES(@TotalVisits,@TotalVisitsALL);

  RETURN;
END

第二种方式是多语句表值用户定义函数(MSTVF)。与内联版本有关的代码结构的主要区别是:

  • 在返回部分中,您必须声明table variable,该函数将返回该{{3}}。它定义了要返回的表的结构。
  • 在正文中你可以指定多个语句,除了副作用或时间依赖的运算符(除非你做了一些肮脏的黑客并跳过一些规则)。
  • 您必须在表变量中插入要返回的结果。插入操作的方式与“常用”表中的方式相同。
  • 您必须在流程结束时添加RETURN语句,但没有任何值可以返回。

答案 1 :(得分:0)

您可以使用Conditional Aggregate根据条件计算行数。请尝试此..

SELECT Count(DISTINCT CASE
                        WHEN dtcreated >= @startdate
                             AND dtcreated <= @enddate
                             AND Service_Id = '1' THEN Invoice_Number
                      END) AS TotalVisits,
       Count(DISTINCT CASE
                        WHEN dtcreated >= @startdate
                             AND dtcreated <= @enddate THEN Invoice_Number
                      END) TotalVisitsALL
FROM   Invoice_Tb 

或者只是

SELECT (SELECT Count(DISTINCT Invoice_Number)
        FROM   Invoice_Tb
        WHERE  dtcreated >= @startdate
               AND dtcreated <= @enddate
               AND Service_Id = '1') AS TotalVisits,
       (SELECT Count(DISTINCT Invoice_Number)
        FROM   Invoice_Tb
        WHERE  dtcreated >= @startdate
               AND dtcreated <= @enddate) AS TotalVisitsALL