Sql 将位字段扩展到多行(类似于连接)

Sql 将位字段扩展到多行(类似于连接),sql,sql-server,bit-fields,bitflags,Sql,Sql Server,Bit Fields,Bitflags,假设我有一张这样的桌子: CREATE TABLE [dbo].[Scheduler]( [DayOfWeek] [tinyint] NOT NULL, [Time] [time](0) NOT NULL, [Action] [varchar](255) NOT NULL ) INSERT INTO Scheduler VALUES (1, '11:00:00', 'Sunday') INSERT INTO Scheduler VALUES (2, '12:00:00'

假设我有一张这样的桌子:

CREATE TABLE [dbo].[Scheduler](
    [DayOfWeek] [tinyint] NOT NULL,
    [Time] [time](0) NOT NULL,
    [Action] [varchar](255) NOT NULL
)
INSERT INTO Scheduler VALUES (1, '11:00:00', 'Sunday')
INSERT INTO Scheduler VALUES (2, '12:00:00', 'Monday')
INSERT INTO Scheduler VALUES (4, '13:00:00', 'Tuesday')
INSERT INTO Scheduler VALUES (8, '14:00:00', 'Wednesday')
INSERT INTO Scheduler VALUES (16, '15:00:00', 'Thursday')
INSERT INTO Scheduler VALUES (32, '16:00:00', 'Friday')
INSERT INTO Scheduler VALUES (64, '17:00:00', 'Saturday')
INSERT INTO Scheduler VALUES (62, '06:00:00', 'Every business day')
INSERT INTO Scheduler VALUES (127, '08:00:00', 'Every day')
还有一些数据,比如:

CREATE TABLE [dbo].[Scheduler](
    [DayOfWeek] [tinyint] NOT NULL,
    [Time] [time](0) NOT NULL,
    [Action] [varchar](255) NOT NULL
)
INSERT INTO Scheduler VALUES (1, '11:00:00', 'Sunday')
INSERT INTO Scheduler VALUES (2, '12:00:00', 'Monday')
INSERT INTO Scheduler VALUES (4, '13:00:00', 'Tuesday')
INSERT INTO Scheduler VALUES (8, '14:00:00', 'Wednesday')
INSERT INTO Scheduler VALUES (16, '15:00:00', 'Thursday')
INSERT INTO Scheduler VALUES (32, '16:00:00', 'Friday')
INSERT INTO Scheduler VALUES (64, '17:00:00', 'Saturday')
INSERT INTO Scheduler VALUES (62, '06:00:00', 'Every business day')
INSERT INTO Scheduler VALUES (127, '08:00:00', 'Every day')
如果DayOfWeek有多个标志,如何在SELECT语句中生成多行

例如,此行:

INSERT INTO Scheduler VALUES (62, '06:00:00', 'Every business day')
它将在SELECT语句中表示为5行(每天一行/标志集一行)

对所有数据运行相同的查询将得到19行

  • 7行-每天一行(1、2、4、8、16、32、64)
  • 5行-工作日(62)
  • 7排-每天(127)
我不知道该怎么做。 我想我可以用光标来做这件事,但这是最好的选择吗

谢谢。

您需要SQL Server的。此示例显示如何确定当前值中包含哪些标志

DECLARE @Mon        INT = 1;
DECLARE @Tue        INT = 2;
DECLARE @Wed        INT = 4;
DECLARE @MonAndTue  INT = 3;    -- Mon (1) and Tue (2) = 3.

SELECT
    @MonAndTue & @Mon,      -- Contains Monday, returns Monday.
    @MonAndTue & @Tue,      -- Contains Tuesday, returns Tuesday.
    @MonAndTue & @Wed       -- Does not contain Wednesday, returns 0.
我建议尽可能避免在SQL Server中使用基于位屏蔽的解决方案。这些在其他语言中非常有效(我想到C语言)。但是,当每一列都包含一个值(描述一个项目)时,SQL工作得最好。当然,你可以把这些方法结合起来。此表设计允许您保留基本的2个键(对于前端来说非常好),并包含简单的位字段,使后端的过滤成为一项简单的任务

CREATE TABLE [Day]
(
    DayId       INT PRIMARY KEY,        
    [DayName]   VARCHAR(9),
    IsMonday    BIT,
    IsTuesday   BIT,
    ...
    IsSunday    BIT
)
;
编辑

对不起!我没有回答你的问题。要在连接中使用逐位操作,您需要以下几行:

WITH Scheduler AS
(
    /* Sample data.
     */
    SELECT          
        *
    FROM
        (
            VALUES  
                (1, 'Sunday'),
                (2, 'Monday'),
                (4, 'Tuesday'),
                (8, 'Wednesday'),
                (16, 'Thursday'),
                (32, 'Friday'),
                (64, 'Saturday'),
                (62, 'Every business day'),
                (127, 'Every day')
        ) AS r(DayId, [DayName])
)
/* This join returns every day from s2 that 
 * is contained within the s1 record Every business day.
 */
SELECT
    *
FROM
    Scheduler AS s1
        INNER JOIN Scheduler AS s2          ON (s1.DayId & s2.DayId) =     s2.DayId
WHERE
    s1.DayId = 62
;

这里S1被过滤以在每个工作日返回。S2连接到S1上找到匹配项的位置。这将返回Mon、Tue、Wed等,而不返回Sat和Sun。

不清楚为什么您的示例会变成这5行,您可以对此进行扩展吗?当然,我可以。。。DayOfWeek=62这分别代表2+4+8+16+32=62:周一+周二+周三+周四+周日。因此,单行表示一周中的5天,相同的任务将运行。这些值都在表中吗?或者你也可以有其他值?我的DayOfWeek列被限制为2^7(0~127),0=none,127全天(整周)在你的例子中应该是64等于周六?是的,就是这样。。。我只需要稍微调整一下,以排除表示一天以上的行(62和127)。s2.DayId在(1,2,4,8,16,32,64)中的什么位置?你认为如果我像你说的那样有多个列(每天一列),应用同样的想法会更容易吗?啊,是的,我忘了62和127会被返回!这取决于你的逻辑在哪里。如果艰苦的工作发生在前端,那么可能不会。但是如果您在SQL中完成所有繁重的工作,那么是的,我会结合位字段来简化过滤。像WHERE IsMonday=1比Day&Day=1更容易读/写/理解。