Estou tentando fazer uma consulta que passa por dados varbinary. O problema é que não consigo terminar o que estou tentando alcançar. O que você deve saber sobre a coluna é varbinary(50) e os padrões que ocorrem não têm ordem específica de escrita, o que significa que cada prefixo pode estar em qualquer lugar, desde que tenha 3 bytes (0x000000) O primeiro byte é o prefixo, o segundo e o terceiro são dados de valor que eu estou olhando para verificar se está dentro do intervalo que eu gosto. Todos os dados são escritos assim.
O que eu tentei:
DECLARE @t TABLE (
val VARBINARY(MAX)
)
INSERT INTO @t SELECT 0x00000100000000000000000000000000000000000000000000000000
INSERT INTO @t SELECT 0x00001000000000000000000000000000000000000000000000000000
INSERT INTO @t SELECT 0x00010000000000000000000000000000000000000000000000000000
INSERT INTO @t SELECT 0x00100000000000000000000000000000000000000000000000000000
INSERT INTO @t SELECT 0x00000f00000000000000000000000000000000000000000000000000
declare @pattern varbinary(max)
declare @pattern2 varbinary(max)
set @pattern = 0x0001
set @pattern2 = @pattern+0xFF
select @pattern,@pattern2
SELECT
*
FROM @t
WHERE val<@pattern
OR val>@pattern2
Isso foi um fracasso total, os padrões eram precisos até 2 símbolos, se eu usasse 4 símbolos como padrão, funcionaria apenas se o padrão estivesse na posição predefinida. Eu tentei a combinação disso e tudo abaixo.
WHERE CONVERT(varbinary(2), val) = 0xdata
também isso:
select *
from table
where CONVERT(varchar(max),val,2) like '%data%'
O que funciona muito bem para pesquisar padrões exatos, mas não para intervalos, preciso de uma combinação de ambos.
Eu preciso de algo que detecte isso por conta própria enquanto eu apenas especifico um ponto inicial e final para procurar entre como a maior variação de número seria '26ffff', mas limitá-lo a algo como 'ff00' é aceitável para o que estou procurando por.
Meu melhor palpite é de 2 números definidos, sendo 1 o intervalo máximo permitido e o 2º para um limite, para que não passe por todos os resultados possíveis. Mas eu ficaria feliz em tudo o que funciona.
A origem dos dados está relacionada a um servidor de jogo que armazena os dados dessa forma. Existem os prefixos predefinidos que são o tipo de estatística e o restante dos dados é o valor numérico real da estatística. Os dados são representados por intervalos de dados de 6 caracteres. Aqui está uma amostra do fluxo de dados. É sempre 6-6-6-6-6, desde que haja espaço para gravar os dados, pois é limitado a 50 caracteres.
0x0329000414000B14000C14000D0F00177800224600467800473C00550F00000000000000000000000000
Os grupos estão sempre na moda de 3 bytes, minha ideia é usar o primeiro byte para restringir a pesquisa e usar os segundos 2 bytes para filtrá-lo. Só não sei como fazer isso de maneira eficaz. Se o padrão de 3 bytes for violado, os dados se tornarão ilegíveis, o que significa que, mesmo que você não precise do byte extra, ainda precisará contá-lo, caso contrário, os dados serão quebrados, exemplo de dados em funcionamento.
0x032900'041400'
exemplo de dados corrompidos:
0x0329'041400'
O único problema que eu poderia pensar é quando o prefixo e parte do valor são verdadeiros exemplo:
0x262600
A menos que a consulta seja especificamente solicitada para ler os dados na sequência de 3 bytes, o que significa que o primeiro byte é sempre um prefixo e os outros 2 bytes são valores.
P: Isso pode ser usado como um indicador de alinhamento para que o primeiro byte diferente de zero após pelo menos 3 bytes zero indique o início de um grupo?
R: Sim, mas isso é improvável, eu quis dizer isso, embora possível, seria escrito em ordem como:
0x260000'270000'
Não pularia para frente um grupo inteiro de 3 bytes preenchido sem dados. Esse tipo de entrada ocorreria se alguém inserisse manualmente no banco de dados, o servidor não faz registros com lacunas como essas que eu saiba:
0x260000'000000'270000'
O mais próximo do meu resultado desejado como uma consulta de trabalho é isso, mas isso é terrível, funcionaria para pequenos intervalos, mas qualquer coisa maior seria tedioso.
select * from @t
where (CONVERT(varchar(max),val,2) like '%262100%' or
CONVERT(varchar(max),attr,2) like '%262200%' or
etc...)
Metas:
- Localizando o prefixo (primeiro par de dados binários)
- Definindo um valor máximo após o prefixo, tudo acima desse limite será listado nos resultados. Digamos que '26' seja o prefixo, o maior número permitido depois é '9600' ou '269600'. Basicamente, qualquer dado que exceda esse padrão '269600' deve ser detectado, exemplo '269700'. ou o resultado da consulta postaria isso:
selecione * da tabela onde CONVERT(varchar(max),attr,2) como '%269700%'
Estou tentando obter uma consulta que pode percorrer os dados varbinary de uma tabela que procura um resultado específico dentro do exemplo de parâmetros definidos:
0x263700, os dados são divididos em segmentos de 3 bytes, 1 byte é o cabeçalho que será usado para um padrão de pesquisa, os outros 2 bytes são o valor que tenho que verificar se está dentro do intervalo definido por exemplo: tudo acima de '3700' (+ 1 bit de diferença) o valor binário até 'FFFF' seria classificado como resultado ou o resultado plausível máximo seria '26FFFF'. Isso não é para um fluxo de dados específico ser alternado um por um.
Provavelmente é mais fácil apenas dividir o valor em blocos de três bytes e examinar cada bloco individualmente.
Como o comprimento máximo é de apenas 50 e você não parece querer olhar para uma janela deslizante de três bytes, é viável apenas codificar os valores de limite na consulta (caso contrário, você pode criar uma tabela com números sequenciais ou usar para evitar
GENERATE_SERIES
isso )O seguinte usa uma junção para retornar o valor de tripleto correspondente e
id
- você pode preferir mudar para aWHERE EXISTS
se quiser apenas a linha correspondente e não quiser várias linhas no caso de várias partes do mesmo valor binário corresponderem.Você também deve revisar se o acima funciona como deseja para o caso em que o comprimento binário não é divisível por três e o último segmento é menor que três bytes (talvez você também precise de um predicado?)
DATALENGTH(Triplet) = 3
.