T-SQL - 使用按位运算查找缺失值[关闭]
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了T-SQL - 使用按位运算查找缺失值[关闭]相关的知识,希望对你有一定的参考价值。
数据库中的示例数据表。
每个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.
我不明白比特标志的目的。虽然我认为你可以总结它们,假设每天没有重复,它实际上并不能简化解码聚合值并拉出缺失天数。这是否符合您的想法?
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;
目前尚不清楚你想用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;
以上是关于T-SQL - 使用按位运算查找缺失值[关闭]的主要内容,如果未能解决你的问题,请参考以下文章
LeetCode810. 黑板异或游戏/455. 分发饼干/剑指Offer 53 - I. 在排序数组中查找数字 I/53 - II. 0~n-1中缺失的数字/54. 二叉搜索树的第k大节点(代码片段