【问题标题】:How to concatenate bits to varbinary with CTE如何使用 CTE 将位连接到 varbinary
【发布时间】:2015-10-03 03:02:48
【问题描述】:

我有一个按以下顺序包含 ID 和位的表:

ID  Bit
1   0
1   0
1   1
1   0
1   0
1   0
1   1
1   0
1   1
1   0
1   ...
... ...
2   0
2   1
2   0
2   0
2   1
2   0
2   0
2   0
2   1
2   0
2   ...
... ...
n   ...

如何使用 CTE 对 ID 列进行分组并将 Bit 列连接到 varbinary 列?

ID  Bits
1   0x...
2   0x...

提前谢谢...

【问题讨论】:

  • 首先您必须知道,您的表中没有固有的排序顺序。有人可能提供的任何解决方案都可能产生随机结果。您必须在您的表格中添加一列“位置”(或类似的)!有了这个,我很快就会提供一个例子。
  • 您能否将示例结果充实?你对 MSB/LSB 的期望并不明显,如何处理不以 8 的倍数出现的位,...。
  • 相同ID的位数上限是否小于64?这样可以很容易地将这些值组合到 BIGINT 中,然后将其改组为 VARBINARY
  • 每个 ID 最多可以有 1920 位。所以我需要一个最大的varbinary。 240 字节。
  • @Shnugo:你是对的。我需要一个职位栏。我有一个订单栏,但我没有写下来,对不起。

标签: sql-server tsql sql-server-2008-r2 common-table-expression


【解决方案1】:
declare @Bits as Table ( Id Int, Position Int, Value Int );
insert into @Bits ( Id, Position, Value ) values
  ( 1, 0, 1 ), ( 1, 1, 1 ), ( 1, 2, 0 ), ( 1, 3, 1 ),
  ( 1, 4, 1 ), ( 1, 5, 1 ), ( 1, 6, 1 ), ( 1, 7, 0 ),
  ( 1, 8, 1 ), ( 1, 9, 0 ), ( 1, 10, 1 ), ( 1, 11, 0 ),
  ( 1, 12, 1 ), ( 1, 13, 1 ), ( 1, 14, 0 ), ( 1, 15, 1 ),
  ( 1, 16, 1 ), ( 1, 17, 0 ), ( 1, 18, 1 ), ( 1, 19, 1 ),
  ( 1, 20, 1 ), ( 1, 21, 1 ), ( 1, 22, 1 ), ( 1, 23, 0 ),
  ( 1, 24, 1 ), ( 1, 25, 1 ), ( 1, 26, 1 ), ( 1, 27, 0 ),
  ( 1, 28, 1 ), ( 1, 29, 1 ), ( 1, 30, 1 ), ( 1, 31, 1 ),
  ( 2, 0, 0 ), ( 2, 1, 1 ), ( 2, 2, 0 ), ( 2, 3, 0 ),
  ( 2, 4, 0 ), ( 2, 5, 0 ), ( 2, 6, 1 ), ( 2, 7, 0 );

select * from @Bits order by Id, Position;

with ExtendedBits as (
  select Id, Position, Value, Position / 4 as NibbleId, Power( 2, 3 - Position % 4 ) * Value as Mask
    from @Bits ),
  Nibbles as (
  select Id, NibbleId, Sum( Mask ) as Nibble
    from ExtendedBits
    group by Id, NibbleId ),
  HexStrings as (
  select Id, Stuff( ( select Substring( '0123456789ABCDEF', Nibble + 1, 1 ) from Nibbles where Id = N.Id order by NibbleId for XML Path( '' ) ), 1, 0, '' ) as HexString
    from Nibbles as N
    group by Id )
  select Id, Cast( '' as xml).value('xs:hexBinary( substring(sql:column("HexString"), 0) )', 'varbinary(max)') as VarBin
    from HexStrings;

请注意,您可以通过将最终的SELECT 替换为select * from ExtendedBitsNibblesHexStrings 来查看中间结果。一种方便的调试技术。

【讨论】:

  • 一些 Hexstrings 使用 Cast('' as xml).value('xs:hexBinary( substring(sql:column("HexString"), 0) )', 'varbinary 为 VarBin 列返回 NULL (最大)“),例如 ”6896A2A62AA869A49A82A4AAA2AA8AAA2AA8AAA2A91A586A89A91A91A68AAA2AA2AA88286AA4AA4AA8AAA2AA86A8668AAA4A68A68AAA1698AA869A2AA2080AA8AA8AA4AA2A68AAA26A2AA2028A98AAA29A00001AAA2A626A02AA8A945A62AA28AA510000000000000000000000000000000000000000000“。不知道为什么:(
  • 我丢失了 1 个 Nibble,因为我的位数据有一个位值 2。所以我得到了一个大于 15 的掩码,子字符串返回一个空字符串。使用不正确的数据是我的错... ;)
  • SQL Server 2008 起,可以使用“convert(varbinary(max), HexString, 2) as VarBin”
【解决方案2】:

这应该可以...

declare @bits TABLE(ID INT, myBit BIT, Position INT);
insert into @bits values(1,0,0)
                       ,(1,0,1)
                       ,(1,1,2)
                       ,(1,0,3)
                       ,(1,0,4)
                       ,(1,0,5)
                       ,(1,1,6)
                       ,(1,0,7)
                       ,(1,1,8)
                       ,(1,0,9)

                       ,(2,0,0)
                       ,(2,1,1)
                       ,(2,0,2)
                       ,(2,0,3)
                       ,(2,1,4)
                       ,(2,0,5)
                       ,(2,0,6)
                       ,(2,0,7)
                       ,(2,1,8)
                       ,(2,0,9);
WITH myIDs AS
(
    SELECT DISTINCT ID
    FROM @bits
)
SELECT '0x' + concatenatedBits.string
FROM myIDs
CROSS APPLY
(
    SELECT
    (
    SELECT CAST(myBit AS VARCHAR(1))
    FROM @bits AS b
    WHERE b.ID=myIDs.ID
    ORDER BY Position
    FOR XML PATH(''),TYPE
    ).value('.','varchar(max)')
) AS concatenatedBits(string)

【讨论】:

  • @HABO,你是什么意思?它只会按照给定的顺序在表格中创建一个由零和一组成的字符串,从“0x”开始。随你所愿...... OP 没有明确说明他将如何处理这个......
  • 嗯,像 "0x00000100" 这样的 VARCHAR 可以通过 CONVERT(VARBINARY,'0x0000000000000100',1) 轻松转换为 VARBINARY,但请注意,“数字”的计数必须除以四跨度>
  • 您的样本值为0010001010 = 0x08A0100100010 = 0x122。 (除非 OP 认为这些值是 LSB 优先。)0x 前缀表示十六进制值,而不是二进制值,
猜你喜欢
  • 2016-12-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-06-24
  • 2016-12-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多