2014-01-09 9 views
6

Gibt es eine Funktion ähnlich der MYSQL BIT_COUNT-Funktion in MSSQL? Ich möchte eine sehr einfache Hammingdistance-Funktion in MSSQL erstellen, die ich in meiner Auswahl verwenden kann.MSSQL BIT_COUNT (Hammingdistance)

Hier ist, was ich für MYSQL haben:

CREATE FUNCTION `HAMMINGDISTANCE`(`hasha` BIGINT, `hashb` BIGINT) 
    RETURNS int(11) 
    DETERMINISTIC 
    RETURN 
    BIT_COUNT(hasha^hashb) 
+2

Verwenden Sie SQL CLR. Muss es [Hamming] sein (http://en.wikipedia.org/wiki/Hamming_distance)? Wie wäre es mit [Levenshtein] (http://en.wikipedia.org/wiki/Levenshtein_distance), gibt es viele Beispiele zur Verfügung. Z.B. http://levenshtein.blogspot.com/ –

+0

Ich brauche Hamming für den Vergleich von Bildern durch generierte Wahrnehmungs-Hashes. Ich werde SQL CLR versuchen, danke. :) –

+0

@Remus Rusanu - Warum braucht er SQL CLR, wenn er nur die Bits zählen muss? Siehe meine Antwort für weitere Details. – dcp

Antwort

5

Warum nicht einfach Ihren eigenen BIT_COUNT Code in T-SQL schreiben? Sie müssen SQL CLR nicht verwenden, wenn Sie nur die Anzahl der gesetzten Bits in einem Bigint zählen müssen. Hier ein Beispiel:

CREATE FUNCTION bit_count 
(
    @pX bigint 
) 
RETURNS int 
AS 
BEGIN 
    DECLARE @lRet integer 
    SET @lRet = 0 
    WHILE (@pX != 0) 
    BEGIN 
     SET @lRet = @lRet + (@pX & 1) 
     SET @pX = @pX/2 
    END 
    return @lRet 
END 
GO 

Auch hier ist ein fiddle können Sie versuchen, diese Funktion in Aktion zu sehen.

Beachten Sie, dass dieser Algorithmus nur bei nicht-negativen Bigints funktioniert. Wenn Sie nach einem Algorithmus suchen, der mit negativen Bigints arbeitet, lesen Sie this link.

+0

Wie machst du den 'hasha^hashb', der die Eingabe für diese Funktion ist? SQL Server [bittet nicht] (bit.net) bitweise Operationen zwischen 'bigint' zu unterstützen (http://technet.microsoft.com/en-us/library/ms190277.aspx). –

+0

Seine Frage war, wie man den bit_count macht, aber Sie bringen eine gute Frage auf. Was macht der Karotte-Operator in MySQL genau? Ich dachte, es sei exklusiv oder, aber das scheint nicht der Fall zu sein, denn XOR ist der exklusive MySQL-Operator oder Operator (http://dev.mysql.com/doc/refman/5.0/en/logical-operators.html #operator_xor). Ich habe MYSQL Karotte Operator gegoogelt, aber keine Treffer bekommen, also bin ich verwirrt. Weißt du, was dieser Operator macht? – dcp

+0

Ich dachte auch XOR. Aber eigentlich scheint 'bigint' * doch zu funktionieren. Bücher, die nur online sind, erwähnen 'int' /' tinyint'/'smallint', aber' DECLARE @B BIGINT = 9223372036854775807; SELECT @B^0' scheint tatsächlich zu funktionieren. –

2

Ich habe gerade eine HAMMINGDISTANCE mit dem mitgelieferten Code von dcp geschrieben und es scheint zu funktionieren.

CREATE FUNCTION [dbo].[HAMMINGDISTANCE](@hasha BIGINT, @hashb BIGINT) 
    RETURNS int 
AS 
BEGIN 
    DECLARE @pX BIGINT 
    DECLARE @lRet integer 
    SET @lRet = 0 
    SET @pX = @hasha^@hashb 
    WHILE (@pX != 0) 
    BEGIN 
     SET @lRet = @lRet + (@pX & 1) 
     SET @pX = @pX/2 
    END 
    return @lRet 
END 

GO 
+0

Froh, dass es funktioniert hat, aber beachte, dass der von mir verwendete Algorithmus nicht für negative Zahlen funktioniert. Sehen Sie meine Bearbeitung, wenn Sie einen Algorithmus dafür benötigen. – dcp

+0

okay danke. –

0
CREATE FUNCTION [dbo].[fn_hamming_distance] 
(
    @a  BIGINT, 
    @b  BIGINT 
) 
RETURNS TINYINT 
AS 
BEGIN 
    DECLARE @c BIGINT = @a^@b 
    RETURN 
    CASE 
     WHEN @c IS NULL 
       THEN NULL 
     ELSE CASE 
        WHEN @c < 0 THEN 1 
        ELSE 0 
       END 
       + 
       CASE 
        WHEN @c & 0x4000000000000000 > 0 THEN 1 
       ELSE 0 
      END 
      + 
      CASE 
       WHEN @c & 0x2000000000000000 > 0 THEN 1 
       ELSE 0 
      END 
      + 
      CASE 
       WHEN @c & 0x1000000000000000 > 0 THEN 1 
       ELSE 0 
      END 
      + 
      CASE 
       WHEN @c & 0x800000000000000 > 0 THEN 1 
       ELSE 0 
      END 
      + 
      CASE 
       WHEN @c & 0x400000000000000 > 0 THEN 1 
       ELSE 0 
      END 
      + 
      CASE 
       WHEN @c & 0x200000000000000 > 0 THEN 1 
       ELSE 0 
      END 
      + 
      CASE 
       WHEN @c & 0x100000000000000 > 0 THEN 1 
       ELSE 0 
      END 
      + 
      CASE 
       WHEN @c & 0x80000000000000 > 0 THEN 1 
       ELSE 0 
      END 
      + 
      CASE 
       WHEN @c & 0x40000000000000 > 0 THEN 1 
       ELSE 0 
      END 
      + 
      CASE 
       WHEN @c & 0x20000000000000 > 0 THEN 1 
       ELSE 0 
      END 
      + 
      CASE 
       WHEN @c & 0x10000000000000 > 0 THEN 1 
       ELSE 0 
      END 
      + 
      CASE 
       WHEN @c & 0x8000000000000 > 0 THEN 1 
       ELSE 0 
      END 
      + 
      CASE 
       WHEN @c & 0x4000000000000 > 0 THEN 1 
       ELSE 0 
      END 
      + 
      CASE 
       WHEN @c & 0x2000000000000 > 0 THEN 1 
       ELSE 0 
      END 
      + 
      CASE 
       WHEN @c & 0x1000000000000 > 0 THEN 1 
       ELSE 0 
      END 
      + 
      CASE 
       WHEN @c & 0x800000000000 > 0 THEN 1 
       ELSE 0 
      END 
      + 
      CASE 
       WHEN @c & 0x400000000000 > 0 THEN 1 
       ELSE 0 
      END 
      + 
      CASE 
       WHEN @c & 0x200000000000 > 0 THEN 1 
       ELSE 0 
      END 
      + 
      CASE 
       WHEN @c & 0x100000000000 > 0 THEN 1 
       ELSE 0 
      END 
      + 
      CASE 
       WHEN @c & 0x80000000000 > 0 THEN 1 
       ELSE 0 
      END 
      + 
      CASE 
       WHEN @c & 0x40000000000 > 0 THEN 1 
       ELSE 0 
      END 
      + 
      CASE 
       WHEN @c & 0x20000000000 > 0 THEN 1 
       ELSE 0 
      END 
      + 
      CASE 
       WHEN @c & 0x10000000000 > 0 THEN 1 
       ELSE 0 
      END 
      + 
      CASE 
       WHEN @c & 0x8000000000 > 0 THEN 1 
       ELSE 0 
      END 
      + 
      CASE 
       WHEN @c & 0x4000000000 > 0 THEN 1 
       ELSE 0 
      END 
      + 
      CASE 
       WHEN @c & 0x2000000000 > 0 THEN 1 
       ELSE 0 
      END 
      + 
      CASE 
       WHEN @c & 0x1000000000 > 0 THEN 1 
       ELSE 0 
      END 
      + 
      CASE 
       WHEN @c & 0x800000000 > 0 THEN 1 
       ELSE 0 
      END 
      + 
      CASE 
       WHEN @c & 0x400000000 > 0 THEN 1 
       ELSE 0 
      END 
      + 
      CASE 
       WHEN @c & 0x200000000 > 0 THEN 1 
       ELSE 0 
      END 
      + 
      CASE 
       WHEN @c & 0x100000000 > 0 THEN 1 
       ELSE 0 
      END 
      + 
      CASE 
       WHEN @c & 0x80000000 > 0 THEN 1 
       ELSE 0 
      END 
      + 
      CASE 
       WHEN @c & 0x40000000 > 0 THEN 1 
       ELSE 0 
      END 
      + 
      CASE 
       WHEN @c & 0x20000000 > 0 THEN 1 
       ELSE 0 
      END 
      + 
      CASE 
       WHEN @c & 0x10000000 > 0 THEN 1 
       ELSE 0 
      END 
      + 
      CASE 
       WHEN @c & 0x8000000 > 0 THEN 1 
       ELSE 0 
      END 
      + 
      CASE 
       WHEN @c & 0x4000000 > 0 THEN 1 
       ELSE 0 
      END 
      + 
      CASE 
       WHEN @c & 0x2000000 > 0 THEN 1 
       ELSE 0 
      END 
      + 
      CASE 
       WHEN @c & 0x1000000 > 0 THEN 1 
       ELSE 0 
      END 
      + 
      CASE 
       WHEN @c & 0x800000 > 0 THEN 1 
       ELSE 0 
      END 
      + 
      CASE 
       WHEN @c & 0x400000 > 0 THEN 1 
       ELSE 0 
      END 
      + 
      CASE 
       WHEN @c & 0x200000 > 0 THEN 1 
       ELSE 0 
      END 
      + 
      CASE 
       WHEN @c & 0x100000 > 0 THEN 1 
       ELSE 0 
      END 
      + 
      CASE 
       WHEN @c & 0x80000 > 0 THEN 1 
       ELSE 0 
      END 
      + 
      CASE 
       WHEN @c & 0x40000 > 0 THEN 1 
       ELSE 0 
      END 
      + 
      CASE 
       WHEN @c & 0x20000 > 0 THEN 1 
       ELSE 0 
      END 
      + 
      CASE 
       WHEN @c & 0x10000 > 0 THEN 1 
       ELSE 0 
      END 
      + 
      CASE 
       WHEN @c & 0x8000 > 0 THEN 1 
       ELSE 0 
      END 
      + 
      CASE 
       WHEN @c & 0x4000 > 0 THEN 1 
       ELSE 0 
      END 
      + 
      CASE 
       WHEN @c & 0x2000 > 0 THEN 1 
       ELSE 0 
      END 
      + 
      CASE 
       WHEN @c & 0x1000 > 0 THEN 1 
       ELSE 0 
      END 
      + 
      CASE 
       WHEN @c & 0x800 > 0 THEN 1 
       ELSE 0 
      END 
      + 
      CASE 
       WHEN @c & 0x400 > 0 THEN 1 
       ELSE 0 
      END 
      + 
      CASE 
       WHEN @c & 0x200 > 0 THEN 1 
       ELSE 0 
      END 
      + 
      CASE 
       WHEN @c & 0x100 > 0 THEN 1 
       ELSE 0 
      END 
      + 
      CASE 
       WHEN @c & 0x80 > 0 THEN 1 
       ELSE 0 
      END 
      + 
      CASE 
       WHEN @c & 0x40 > 0 THEN 1 
       ELSE 0 
      END 
      + 
      CASE 
       WHEN @c & 0x20 > 0 THEN 1 
       ELSE 0 
      END 
      + 
      CASE 
       WHEN @c & 0x10 > 0 THEN 1 
       ELSE 0 
      END 
      + 
      CASE 
       WHEN @c & 0x8 > 0 THEN 1 
       ELSE 0 
      END 
      + 
      CASE 
       WHEN @c & 0x4 > 0 THEN 1 
       ELSE 0 
      END 
      + 
      CASE 
       WHEN @c & 0x2 > 0 THEN 1 
       ELSE 0 
      END 
      + 
      CASE 
       WHEN @c & 0x1 > 0 THEN 1 
       ELSE 0 
      END 
    END 
END 
+0

Vielen Dank für Ihre Antwort. Erwägen Sie, eine Erklärung hinzuzufügen, wie dies das Problem des Fragestellers löst. –