获得员工每月出勤率

时间:2018-02-15 10:51:45

标签: sql-server

我有一个问题,一个人在这里帮助开发,这给了很好的结果。我想在一个函数中使用这个查询,以后我想在一个过程中使用它。

CREATE FUNCTION [dbo].[fnGetWorkedDays] (@StartDate datetime, @EndDate datetime)
RETURNS int
AS
BEGIN
     DECLARE @dateFrom datetime 
     DECLARE @dateTo datetime 
     SET @dateFrom = @StartDate 
     SET @dateTo = @EndDate


     DECLARE @DAYSWORKED INT   
     SELECT @DAYSWORKED = (
   SELECT EmpId,  COUNT(*) as DaysWorked 
    FROM
    (
      SELECT DISTINCT EmpId,CAST(TimeIn AS DATE) AS [Date]
      FROM myTable
      WHERE TimeIn IS NOT NULL
      AND CAST(TimeIn AS DATE) BETWEEN @StartDate AND @EndDate
    )T
    GROUP BY EmpId
    ORDER BY EmpId)
RETURN ISNULL(@DAYSWORKED,0)

END

我得到的第一个错误是

Msg 1033, Level 15, State 1, Procedure fnGetWorkedDays, Line 24
The ORDER BY clause is invalid in views, inline functions, derived tables, subqueries, and common table expressions, unless TOP, OFFSET or FOR XML is also specified.

我删除了ORDER BY然后又收到了另一个错误

Msg 116, Level 16, State 1, Procedure fnGetWorkedDays, Line 25
Only one expression can be specified in the select list when the subquery is not introduced with EXISTS.

2 个答案:

答案 0 :(得分:3)

我建议你去了解更多关于表值函数和标量值函数Difference between scalar, table-valued, and aggregate functions in SQL server?

关于你的场景,你应该为此编写一个表值函数,如下所示。

CREATE FUNCTION [dbo].[fnGetWorkedDays]
 (
  @StartDate AS DATETIME,
  @EndDate datetime
 )
RETURNS TABLE
AS
RETURN
   SELECT EmpId,  COUNT(*) as DaysWorked 
    FROM
    (
      SELECT DISTINCT EmpId,CAST(TimeIn AS DATE) AS [Date]
      FROM myTable
      WHERE TimeIn IS NOT NULL
      AND CAST(TimeIn AS DATE) BETWEEN @StartDate AND @EndDate
    )T
    GROUP BY EmpId

要使用此功能,您可以编写如下的查询。

DECLARE @StartDate datetime
DECLARE @EndDate datetime
SET @StartDate = '2018-01-01'
SET @EndDate = '2018-01-31'
select * from  [dbo].[fnGetWorkedDays](@StartDate,@EndDate)

如果您希望它作为标量值函数运行,那么您需要将EmpId作为参数传递,如下所示。

CREATE FUNCTION [dbo].[fnGetWorkedDaysEmpWise]
 (
  @StartDate AS DATETIME,
  @EndDate datetime,
  @EmpId INT
 )
RETURNS INT
AS
BEGIN
DECLARE @RetunCount INT

      SELECT @RetunCount = COUNT(DISTINCT CAST(TimeIn AS DATE))
      FROM myTable
      WHERE TimeIn IS NOT NULL
      AND CAST(TimeIn AS DATE) BETWEEN @StartDate AND @EndDate
      AND EmpID=@EmpId
      RETURN @RetunCount

  END 

您可以直接在select子句中使用它,如下所示。

DECLARE @StartDate datetime
DECLARE @EndDate datetime
SET @StartDate = '2018-01-01'
SET @EndDate = '2018-01-31'
SELECT [dbo].[fnGetWorkedDaysEmpWise](@StartDate,@EndDate,1)

答案 1 :(得分:0)

这就是你要找的。?

CREATE FUNCTION [dbo].[fnGetWorkedDays] (@StartDate datetime, @EndDate datetime)
RETURNS @DaysWorked TABLE   
   (  
 Empid Int,   
    DaysWorked  Int   
   ) 
AS
BEGIN 


insert into @DaysWorked (Empid,DaysWorked)

  SELECT EmpId,  COUNT(*) as DaysWorked 
    FROM
    (
      SELECT DISTINCT EmpId,CAST(TimeIn AS DATE) AS [Date]
      FROM myTable
      WHERE TimeIn IS NOT NULL
      AND CAST(TimeIn AS DATE) BETWEEN @StartDate AND @EndDate
    )T
    GROUP BY EmpId
    ORDER BY EmpId

     RETURN 
END

select * from [fnGetWorkedDays]('2018-01-01','2018-01-31')