#sql #teradata
#sql #teradata
Вопрос:
Точно так же, как у нас есть агрегатные функции sum и count, есть ли какой-нибудь способ сделать агрегированные хэши в поле? Например, предположим, что у вас есть следующий набор записей:
Name ID
Bob 1
Bob 2
Bob 3
Bob 4
Концептуально я хотел бы сделать это:
select name, hash(id) from mydb.mytable
group by 1
… который вернет это:
Name ID
Bob D8-F0-00-91
Если я удалю запись с ID = 3, агрегат вернет это:
Name ID
Bob A8-EB-6D-1D
К вашему сведению, я использовал select hashrow(1,2,3,4)
и select hashrow(1,2,4)
для получения вышеуказанных значений хэша.
Обновление для dnoeth: вероятно, полезно упомянуть, что мне нужно, чтобы результирующий агрегат был уникальным. Вот пример модели данных, которую я использую:
table office (Id integer)
table employee (Id integer, OfficeId integer)
В каждом офисе есть сотрудники, так что это один ко многим от office к employee с таблицей employee, имеющей OfficeId в качестве FK для таблицы office.
locking row for access
select n, count(n) from
(
select
officeid,
sum(cast(from_bytes('00'xb || hashrow(id), 'base10') as bigint)) n
from mydb.employee
group by 1
) x
group by 1
Вот отличный пример того, как происходит столкновение. Опять же, я не упомянул, что мне нужно, чтобы результат был уникальным.
select
cast(from_bytes('00'xb || hashrow(2300015), 'base10') as bigint)
cast(from_bytes('00'xb || hashrow(14100028), 'base10') as bigint) hash1,
cast(from_bytes('00'xb || hashrow(1000004), 'base10') as bigint)
cast(from_bytes('00'xb || hashrow(3100014), 'base10') as bigint)
cast(from_bytes('00'xb || hashrow(12300025), 'base10') as bigint) hash2
Комментарии:
1. Существуют функции, связанные с хэшем. Чего вы пытаетесь достичь?
2. @RobPaller Я обновил свой ответ для большей ясности.
Ответ №1:
Вам нужно преобразовать результат хэш-строки в числовое значение, затем вы можете легко его суммировать.
-- HASHROW to unsigned integer, TD14
SUM(CAST(FROM_BYTES('00'xb||HASHROW(ColumnName), 'base10') AS BIGINT)
) AS SumHash
-- HASHROW to unsigned integer, pre-TD14
SUM( HASHBUCKET( HASHROW(ColumnName) (BYTE(4))) / ((HASHBUCKET() 1)/65536) * CAST(65536 AS BIGINT)
HASHBUCKET(SUBSTR(HASHROW(ColumnName),3,2) (BYTE(4))) / ((HASHBUCKET() 1)/65536)
) AS SumHash
Редактировать:
Нет способа получить гарантированный уникальный результат при хешировании, есть только возрастающая вероятность, основанная на длине вычисляемого хэша. И HASHROW возвращает значение в 4 байта, и вы просто добавляете их:-(
Вы могли бы установить существующий UDF хэширования, возвращающий более 4 байт, например
https://downloads.teradata.com/download/extensibility/sha-1-message-digest-udf
https://downloads.teradata.com/download/extensibility/md5-message-digest-udf
https://github.com/akuroda/teradata-udf-sha2
а затем реализовать агрегатный XOR UDF.
На DevEx от Teradata был блог о сравнении таблиц:
Комментарии:
1. Вероятно, мне следовало упомянуть, что мне нужно, чтобы агрегированный результат был уникальным (именно поэтому агрегированный хэш был бы отличным). Когда я 1) выполняю ваш метод SUM для поля UPI в таблице с 10 тыс. строк, 2) группирую по родительскому внешнему ключу, а затем 3) подсчитываю суммированные результаты, я получаю некоторые коллизии. Я полагаю, что это тот же тип коллизии, который вы получите при добавлении 10, 30, 50, 70, чтобы получить 160, а затем возьмите совершенно разные числа 5, 35, 40, 80 и также получите 160. Я обновил свой ответ некоторым примером SQL.
2. Хммм… Интересно, будет ли работать «кумулятивный» хэш. По сути, генерируйте хэш, а затем хэшируйте этот хэш с помощью хэша предыдущей строки. Или, возможно, есть способ создать совокупный целочисленный массив, а затем передать этот массив
hashrow()
. Я просто думаю, на самом деле.3. В ответ на ваше редактирование я знаю, что хэши не гарантированно уникальны, но я думаю, что суммирование случайных групп хэшей значительно увеличивает вероятность столкновения. Я только что использовал hashrow() для UPI в таблице с 11 тыс. записей, и каждая из них была уникальной, но суммирование групп этих хэшей привело к значительному количеству коллизий (см. Мой предыдущий пример 10,30,50,70). Во всяком случае, я думаю, мы можем сделать вывод, что ответ отрицательный, агрегатной хеш-функции не существует и что потребуется использовать какой-то другой метод, такой как UDFs, как вы предложили.