T-SQL - 使用按位运算查找缺失值[关闭]

问题描述 投票:-1回答:2

数据库中的示例数据表。

每个ID1 / ID2组合组都缺少一些日子

DECLARE @Week_DataTable TABLE 
    (
        [ID1]      INT
      , [ID2]      INT
      , [Day_Enum] INT
      , [IsActive] BIT DEFAULT ( 0 )
    ) ;

INSERT INTO @Week_DataTable
    (
        [ID1]
      , [ID2]
      , [Day_Enum]
      , [IsActive]
    )
VALUES
    ( 1, 1, 1, 0 )
  , ( 1, 1, 2, 0 )
  , ( 1, 1, 3, 0 )
  , ( 1, 1, 4, 0 )
  , ( 1, 1, 5, 0 )
  , ( 1, 1, 6, 0 )
  , ( 1, 1, 7, 0 )

  , ( 1, 2, 1, 0 )

  , ( 1, 2, 3, 0 )
  , ( 1, 2, 4, 0 )
  , ( 1, 2, 5, 0 )
  , ( 1, 2, 6, 0 )

  , ( 1, 3, 1, 0 )
  , ( 1, 3, 2, 0 )
  , ( 1, 3, 3, 0 )
  , ( 1, 3, 4, 0 )
  , ( 1, 3, 5, 0 )


  , ( 1, 4, 1, 0 )
  , ( 1, 4, 2, 0 )


  , ( 1, 4, 5, 0 )
  , ( 1, 4, 6, 0 )
  , ( 1, 4, 7, 0 ) ;

SELECT * FROM @Week_DataTable

一个查找表,用于查找@Week_DataTable中缺少的天数,其中[Validate] = 1 Join key field = [Day_Enum] field Bitwise logic(field = [Code])应该用于查找@Week_DataTable中的缺失天数

   DECLARE @Days TABLE
    (
        [Day_Id]   INT        NOT NULL IDENTITY(1, 1)
      , [Day_Enum] INT        NOT NULL
      , [Day_Name] VARCHAR(9) NOT NULL
      , [Code]     INT        NOT NULL DEFAULT ( 0 )
      , [Validate] BIT        NOT NULL DEFAULT ( 1 )
    ) ;

INSERT INTO @Days
    (
        [Day_Enum]
      , [Day_Name]
      , [Code]
      , [Validate]
    )
SELECT  [V].[Day_Enum]
      , [V].[Day_Name]
      , [V].[Code]
      , [V].[Validate]
FROM    (
            VALUES
                ( 1, 'Monday', 1, 0 )
              , ( 2, 'Tuesday', 2, 0 )
              , ( 3, 'Wednesday', 4, 0 )
              , ( 4, 'Thursday', 8, 0 )
              , ( 5, 'Friday', 16, 0 )
              , ( 6, 'Saturday', 32, 1 )
              , ( 7, 'Sunday', 64, 1 )
        ) [V] ( [Day_Enum], [Day_Name], [Code], [Validate] ) ;

SELECT  *
FROM    @Days ;

目标:使用@Week_DataTable查找表@Days查询where [Validate] = 1表中的缺失日期。必须使用按位操作([代码])进行此操作。

更新:抱歉,忘记提前包含所需的输出。还添加了[Valid]标志背后的原因。期望的输出

ID1 ID2 Day_Enum    IsActive
1   1   1   0
1   1   2   0
1   1   3   0
1   1   4   0
1   1   5   0
1   1   6   0
1   1   7   0
1   2   1   0

1   2   3   0
1   2   4   0
1   2   5   0
1   2   6   0
1   2   7   0
1   3   1   0
1   3   2   0
1   3   3   0
1   3   4   0
1   3   5   0
1   3   6   0
1   3   7   0
1   4   1   0
1   4   2   0


1   4   5   0
1   4   6   0
1   4   7   0

有效标志指示查询应查找哪些丢失的日期。如果仅对Sat / Sun有效,则查询应从数据表中找到所有缺少的Sat / Sun.

sql sql-server tsql sql-server-2012
2个回答
2
投票

我不明白比特标志的目的。虽然我认为你可以总结它们,假设每天没有重复,它实际上并不能简化解码聚合值并拉出缺失天数。这是否符合您的想法?

select ID1, ID2, sum(Code),
    replace('Missing:' +
      case when sum(Code) & 0x01 = 0 then ', Monday'    else '' end +
      case when sum(Code) & 0x02 = 0 then ', Tuesday'   else '' end +
      case when sum(Code) & 0x04 = 0 then ', Wednesday' else '' end +
      case when sum(Code) & 0x08 = 0 then ', Thursday'  else '' end +
      case when sum(Code) & 0x10 = 0 then ', Friday'    else '' end +
      case when sum(Code) & 0x20 = 0 then ', Saturday'  else '' end +
      case when sum(Code) & 0x40 = 0 then ', Sunday'    else '' end, ':,', ':') as Summary

from @Week_DataTable w inner join @Days d on d.Day_Enum = w.Day_Enum
group by ID1, ID2
having sum(Code) < (select sum(Code) from @Days); -- or just 127

编辑:根据您的编辑,我认为您只是在寻找标准的密集查询。我仍然没有看到位操作的必要性。

with combos as (select ID1, ID2 from @Week_DataTable group by ID1, ID2),
    days as (select * from @Days where Valid = 1)
select
from combos c cross join days d
    left outer join @Week_DataTable w
        on w.ID1 = c.ID1 and w.ID2 = c.ID2 and w.Day_Enum = d.Day_Enum
where w.Day_Enum is null;

1
投票

目前尚不清楚你想用Validate做什么,但我希望它可以很容易地包含在下面的代码示例中。

您可以使用sum收集所包含日期的位掩码:

-- Get a bitmask of days for each Id1/Id2 pair.
select WDT.ID1, WDT.ID2, Sum( D.Code ) as BitMask
  from @Week_DataTable as WDT inner join
    @Days as D on D.Day_Enum = WDT.Day_Enum
  group by WDT.ID1, WDT.ID2;

使用exclusive或者很容易生成省略的日期:

-- Get missing days for each Id1/Id2 pair.
select WDT.ID1, WDT.ID2, 127 ^ Sum( D.Code ) as OmittedBitMask
  from @Week_DataTable as WDT inner join
    @Days as D on D.Day_Enum = WDT.Day_Enum
  group by WDT.ID1, WDT.ID2;

通过检查每个位,结果可以显示为缺失天数表:

-- Get missing days for each Id1/Id2 pair by day.
with OmittedDays as (
  select WDT.ID1, WDT.ID2, 127 ^ Sum( D.Code ) as OmittedBitMask
    from @Week_DataTable as WDT inner join
      @Days as D on D.Day_Enum = WDT.Day_Enum
    group by WDT.ID1, WDT.ID2 )
  select *
    from OmittedDays as OD inner join
      @Days as D on D.Code & OD.OmittedBitMask = D.Code
    order by OD.ID1, OD.ID2, D.Day_Enum;
© www.soinside.com 2019 - 2024. All rights reserved.