SQL Hashbyte для набора значений в нескольких строках

#sql #checksum

#sql #контрольная сумма

Вопрос:

У меня есть таблица, как показано ниже. Я вставляю данные в пакеты. Я хотел бы узнать, содержит ли пакет одинаковые значения:

 ID    Package   Value
1     A         001
2     A         002
3     A         004
---
12    C         001
13    C         002
14    C         009
---
20    F         001
21    F         002
---
25    G         001
26    G         002
27    G         004
 

Интересно, как поместить значения для каждого пакета в контрольную сумму (хэш-байт?) и сравнить. Это должно позволить выяснить, что пакет A и пакет G имеют одинаковое содержимое

Я обнаружил, что контрольная сумма_agg недостаточно хороша, так как значения являются переменными

Комментарии:

1. Какую СУБД вы используете?

2. Помните, что язык SQL по своей конструкции не определяет, как сравнения выполняются механизмом. На самом деле вам нужна обычная операция set. Вам не нужно указывать, что следует использовать хэш-набор.

Ответ №1:

Используйте операторы SQL Set ( UNION , INTERSECT , EXCEPT , и т.д.), Чтобы увидеть, эквивалентны ли два произвольных набора кортежей:

 CREATE FUNCTION dbo.PackagesAreEquivalent( @packageX nvarchar(10), @packageY nvarchar(10) )
    RETURNS bit
AS

DECLARE @ret bit = (
    CASE
        WHEN EXISTS(
            SELECT
                [Value]
            FROM
                MyTable
            WHERE
                Package = @packageX

            EXCEPT

            SELECT
                [Value]
            FROM
                MyTable
            WHERE
                Package = @packageY
        ) THEN 1 ELSE 0
    END
);

RETURN @ret;

END;
 

Использование:

 SELECT dbo.PackagesAreEquivalent( 'A', 'G' );
 

Ответ №2:

Вы можете использовать агрегацию строк. В стандартном SQL это используется LISTAGG() , но точное имя функции зависит от базы данных. Идея заключается в:

 select value_list, listagg(package, ',') within group (order by package) as packages
from (select package,
             listagg(value, ',') within group (order by value) as value_list
      from t
      group by package
     ) p
group by value_list
having count(*) > 1;
 

Обратите внимание, что функция «hash» не поможет, поскольку она будет работать только в пределах одной строки.

Ссылка на checksum_agg() предполагает, что вы используете SQL Server. Если это так, то функция для агрегирования строк такова string_agg() .

Комментарии:

1. ПОКА я не узнал о LISTAGG (спасибо!) — но после того, как я прочитал об этом из спецификации, я теперь увядаю в своем пессимистичном мнении, что комитет ISO SQL неуклюж в своих синтаксических изобретениях только потому, что они могут . Я собираюсь стать богатым и знаменитым после того, как закончу разработку своего «Что МЕНЬШЕ / SASS для CSS, мое (дело) для SQL». У меня есть доказательство концепции, работающее путем взлома SSMS через .NET reflection, и это не красиво. Дайте мне знать, если вам интересно!