直接查询返回表的函数时,按位使用t-sql

时间:2014-07-14 14:51:24

标签: sql sql-server tsql bit-manipulation user-defined-functions

以下函数返回给定员工的可用性列表。

有时,数据在同一日期的两行中保存在数据库中,所以我想对出现多次的日期执行BITWISE OR(|)(例如:2014-11 -27在以下结果中)

SELECT * FROM dbo.fnWebGetAvailability('10436837-7AA9-4012-BE66-CA33D0FA084D','2014-11-25','2014-11-30')

MyAvailabilityDate Night Day   Evening NA    Vacation
------------------ ----- ----- ------- ----- --------
2014-11-25         0     1     1       0     0
2014-11-26         0     0     0       0     0
2014-11-27         0     0     1       0     0
2014-11-27         1     0     0       0     0
2014-11-28         0     0     0       0     0
2014-11-29         0     0     0       0     0
2014-11-30         0     0     0       0     0

我目前的工作是围绕GROUP BY MyAvailabilityDate并在SUM列表中执行SELECT。这只能在函数中直接实现时才能正常工作,但在直接查询函数时却无法正常工作。

SELECT MyAvailabilityDate, SUM(CAST(Night AS int)),SUM(CAST(Day as int)),SUM(CAST(Evening as int)),NA,Vacation 
FROM dbo.fnWebGetAvailability('10436837-7AA9-4012-BE66-CA33D0FA084D','2014-11-25','2014-11-30') GROUP BY MyAvailabilityDate,CAST(Night AS int),CAST(Day as int),CAST(Evening as int),NA,Vacation

我不喜欢这种实现,因为列数据类型需要从BIT更改为INT,之后我必须记住使用>= 1而不是= 1

直接查询我的功能时如何使用BITWISE OR

编辑:我认为没有必要,但这是函数的代码:

USE [MyDataBase]
GO

/****** Object:  UserDefinedFunction [dbo].[fnWebGetAvailability]    Script Date: 2014-07-14 10:51:38 ******/
SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO


ALTER FUNCTION [dbo].[fnWebGetAvailability] 
(
@MyUserID Uniqueidentifier
,@MyAvailabilityDateFrom DATE
,@MyAvailabilityDateTo DATE
)

RETURNS @MaTable TABLE
(
MyAvailabilityDate DATE,
Night INT,
Day INT,
Evening INT,
NA INT,
Vacation INT
)

AS
BEGIN

DECLARE @MyUserStreamID UNIQUEIDENTIFIER = (SELECT ID FROM UserStreams WHERE USerID = @MyUserID AND DefaultStream = 1)
INSERT INTO @MaTable 

SELECT dt.Date AS MyAvailabilityDate
    ,SUM(ISNULL(CAST(usd.N AS int),0)) AS Night
    ,SUM(ISNULL(CAST(usd.J AS int),0)) AS Day
    ,SUM(ISNULL(CAST(usd.S AS int),0)) AS Evening
    ,CASE WHEN EXISTS (SELECT NULL FROM UserHolidays as us1 WHERE us1.UserStreamID = @MyUserStreamID AND us1.FromDate = dt.date AND (Description IS NULL OR Description LIKE '')) THEN 1
        ELSE 0 END AS NA
    ,CASE WHEN EXISTS (SELECT NULL FROM UserHolidays as us2 WHERE us2.UserStreamID = @MyUserStreamID AND us2.FromDate = dt.date AND Description LIKE 'Vacation') THEN 1
        ELSE 0 END AS Vacation
    FROM dbo.fnDatesTable(@MyAvailabilityDateFrom,@MyAvailabilityDateTo) As dt
        LEFT JOIN UserSpecialDays as usd on dt.Date = usd.FromDate and usd.UserStreamId = @MyUserStreamID
        LEFT JOIN UserHolidays as uh on dt.Date = uh.FromDate and uh.UserStreamId = @MyUserStreamID 
    GROUP BY dt.Date
RETURN 
END
GO

2 个答案:

答案 0 :(得分:1)

使用MAX()代替SUM()

SELECT MyAvailabilityDate, MAX(CAST(Night AS int)),MAX(CAST(Day as int)),MAX(CAST(Evening as int)),NA,Vacation 
FROM dbo.fnWebGetAvailability('10436837-7AA9-4012-BE66-CA33D0FA084D','2014-11-25','2014-11-30') GROUP BY MyAvailabilityDate,CAST(Night AS int),CAST(Day as int),CAST(Evening as int),NA,Vacation

答案 1 :(得分:0)

BITWISE OR aggregate可以使用下一个技巧进行模拟:

SELECT 
   MAX(field&1)+MAX(field&2)+MAX(field&4)+...+MAX(field&1073741824)+MIN(field&0x80000000) AS bitwise_or_of_field
 FROM
    tbl

(将省略号替换成两个缺失的省略号)

它非常冗余但有效。