【问题标题】:Using t-sql bitwise when querying directly a function that returns a table直接查询返回表的函数时按位使用 t-sql
【发布时间】:2014-07-14 14:51:24
【问题描述】:

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

有时,数据在同一日期的两行下保存在数据库中,因此我想对出现多次的日期执行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

我目前的工作是按 MyAvailabilityDate 分组并在SELECT 列表中执行SUM。这只有在直接在函数中实现时才能正常工作,但在直接查询函数时不起作用。

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

【问题讨论】:

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


    【解决方案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
    

    【讨论】:

    • 使用 MAX() 将避免我使用 >=1 但非常令人满意,但真正的问题是:“直接查询我的函数时如何使用 BITWISE 或?”
    • BITWISE OR 是一个运算符。运算符作用于列。聚合器作用于行。如果要聚合多行中的值,则不要使用运算符来执行此操作。您的问题是,“如何使用快速排序来添加两个数字?”
    【解决方案2】:

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

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

    (将省略号替换为其他缺失的 2 次方)

    这是非常多余的,但有效。

    【讨论】:

      猜你喜欢
      • 2010-10-07
      • 1970-01-01
      • 1970-01-01
      • 2018-03-18
      • 1970-01-01
      • 2017-10-21
      • 1970-01-01
      • 2018-03-21
      • 1970-01-01
      相关资源
      最近更新 更多