MSSQLServerの場合
DECLARE @agg VARCHAR(MAX) = '0001,0011,0101,0101,0101'
SELECT CONVERT(binary(4), VALUE, 2) , VALUE FROM STRING_SPLIT( @agg , ',')
DECLARE @sum AS BIGINT = 0
DECLARE @mul AS BIGINT = 0xffffffff
SELECT @sum |= v
, @mul &= v
FROM STRING_SPLIT( @agg , ',')
CROSS APPLY (VALUES (CONVERT(binary(4), VALUE, 2))) _(v)
PRINT FORMAT(@sum,'X8')
PRINT FORMAT(@mul,'X8')
プリント
VALUE
---------- ------------
0x00010000 0001
0x00110000 0011
0x01010000 0101
0x01010000 0101
0x01010000 0101
01110000
00010000
より複雑な言葉であなたが必要とする:
CREATE OR ALTER FUNCTION dbo.BOR( @agg VARCHAR(MAX))
RETURNS BIGINT
AS
BEGIN
DECLARE @sum AS BIGINT = 0
SELECT @sum |= CONVERT(BIGINT, VALUE)
FROM STRING_SPLIT( @agg , ',')
RETURN @sum
END
GO
CREATE OR ALTER FUNCTION dbo.BAND( @agg VARCHAR(MAX))
RETURNS BIGINT
AS
BEGIN
DECLARE @mul AS BIGINT = 0xffffffffffffffff
SELECT @mul &= CONVERT(BIGINT, VALUE)
FROM STRING_SPLIT( @agg , ',')
RETURN @mul
END
GO
支払い期間のビットマップを使用する場合
;WITH delayedPayment AS
(SELECT * FROM ( VALUES
( 123, 67, '2020-2-1')
,( 123, 67, '2020-4-1')
,( 123, 67, '2020-5-1')
,( 123, 67, '2020-6-1')
,( 123, 68, '2020-6-1') -- another agreement
,( 123, 67, '2020-12-1')
,( 456, 69, '2020-4-1')
,( 456, 69, '2020-8-1')
,( 456, 69, '2020-10-1')
,( 456, 69, '2020-11-1')) _(cuno, loan, missedDuedate)
)
, delayPattern AS
(SELECT cuno
, sum_months
, bor_months
, IIF( FORMAT( CAST(bor_months AS BIGINT), 'X16') LIKE '%111%', 'dalyad 3+ month in row', NULL) delayState
FROM (SELECT cuno
, SUM(POWER( 16.0, CONVERT( BIGINT, DATEDIFF( month, missedDuedate, '2020-12-1')))) sum_months
, dbo.BOR( STRING_AGG( CONVERT( BIGINT, POWER( 16.0, DATEDIFF( month, missedDuedate, '2020-12-1'))),',')) bor_months
FROM delayedPayment
GROUP BY cuno
) s
)
SELECT cuno
, FORMAT( CAST(sum_months AS BIGINT), 'X16') sum_months
, FORMAT( CAST(bor_months AS BIGINT), 'X16') bor_months
, delayState
FROM delayPattern
cuno sum_months bor_months delayState
123 00000*10112*000001 00000*10111*000001 dalyad 3+ month in row
456 0000000100010110 0000000100010110 NULL
しかし、たまに1つだけ考える必要があり、SUMでそれを行うことができます
, delayPattern AS -- optimal
(SELECT cuno
, bor_months
, IIF( FORMAT( CAST(bor_months AS BIGINT), 'X16') LIKE '%111%', 'dalyad 3+ month in row', NULL) delayState
FROM (SELECT cuno
, SUM(POWER( 16.0, missedmonth)) bor_months
FROM ( SELECT DISTINCT cuno
, missedmonth
FROM delayedPayment
CROSS APPLY (VALUES ( DATEDIFF( month, missedDuedate, '2020-12-1'))) _(missedmonth)
GROUP BY cuno, missedmonth
) ss
GROUP BY cuno
) s
)
SELECT cuno
, FORMAT( CAST(bor_months AS BIGINT), 'X16') bor_months
, delayState
FROM delayPattern
印刷します
cuno bor_months delayState
123 0000010111000001 dalyad 3+ month in row
456 0000000100010110 NULL
注:私はHEX形式とPOWER(16.0、X)を使用していますが、怠惰になるために、POWER(2.0、X)は正しいですが、bin->stringフォーマッターが必要です。このようなもの:
CREATE OR ALTER FUNCTION dbo.toBinaryString(@p INT)
RETURNS VARCHAR(24)
AS
BEGIN
RETURN REVERSE(REPLACE( REPLACE(
REPLACE( REPLACE( REPLACE( REPLACE(
REPLACE( REPLACE( REPLACE( REPLACE(
REPLACE( REPLACE( REPLACE( REPLACE(
REPLACE( REPLACE( REPLACE( REPLACE( FORMAT(@p,'X8'),
'0', '....'), '1', '...x'),'2', '..x.'),'3', '..xx'),
'4', '.x..'), '5', '.x.x'),'6', '.xx.'),'7', '.xxx'),
'8', 'x...'), '9', 'x..x'),'A', 'x.x.'),'B', 'x.xx'),
'C', 'xx..'), 'D', 'xx.x'),'E', 'xxx.'),'F', 'xxxx'),
'.','0'),'x','1'))
END