2014-01-09 4 views
6

MSSQL의 MYSQL BIT_COUNT 함수와 유사한 함수가 있습니까? 내 선택에 사용할 수있는 MSSQL에서 매우 간단한 Hammingdistance 함수를 만들고 싶습니다. 여기MSSQL BIT_COUNT (해밍 거리)

내가 MYSQL을 위해 무엇을 가지고 :

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

를 사용하여 SQL CLR. 그것은해야한다 [Hamming] (http://en.wikipedia.org/wiki/Hamming_distance)? 어때 [Levenshtein] (http://en.wikipedia.org/wiki/Levenshtein_distance), 많은 예제를 사용할 수 있습니다. 예 : http://levenshtein.blogspot.com/ –

+0

생성 된 지각 해시로 이미지를 비교하기 위해 해밍이 필요합니다. SQL CLR에 감사를 표할 것입니다. :) –

+0

@Remus Rusanu - 필요한 모든 것이 비트 계산에 필요한 경우 SQL CLR이 필요한 이유는 무엇입니까? 자세한 내용은 내 대답을 참조하십시오. – dcp

답변

5

이유는 단지 T-SQL에서 자신의를 bit_count 코드를 작성하지? bigint의 비트 수를 세는 것이 필요한 경우 SQL CLR을 사용할 필요가 없습니다.

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 

는 또한, 여기 당신이 행동이 기능을보기 위해 시도 할 수있는 fiddle의 예를 들면 다음과 같습니다.

이 알고리즘은 음수가 아닌 bigints에서만 작동합니다. 부정적인 bigints에서 작동하는 알고리즘을 찾으려면 this link을 참조하십시오.

+0

이 함수에 대한 입력 인'hasha^hashb '은 어떻게하고 있습니까? SQL Server는 'bigint'사이의 비트 연산 (http://technet.microsoft.com/en-us/library/ms190277.aspx)을 지원하지 않습니다. –

+0

그의 질문은 bit_count를 수행하는 방법 이었지만 좋은 질문이 제기되었습니다. 정확히 당근 연산자는 MySQL에서 무엇을합니까? XOR은 MySQL의 독점 또는 운영자이므로 배타적이라고 생각했습니다. (http://dev.mysql.com/doc/refman/5.0/en/logical-operators.html) #operator_xor). 나는 MYSQL 당근 조작원을 봤지만 안타를 쳐 내지 못해 혼란스러워. 그 운영자가 무엇을하는지 알아? – dcp

+0

나는 XOR을 또한 생각했다. 그러나 실제로'bigint'를 테스트 한 결과 * 결국 효과가있는 것 같습니다. 온라인 서적은'int' /'tinyint' /'smallint'를 언급하지만'DECLARE @B BIGINT = 9223372036854775807; SELECT @B^0'는 실제로 잘 동작하는 것처럼 보입니다. –

2

방금 ​​dcp가 제공 한 코드를 사용하여 HAMMINGDISTANCE를 작성했으며 제대로 작동하는 것 같습니다.

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

다행 이었지만, 내가 사용한 알고리즘은 음수에서는 작동하지 않습니다. 이를 위해 알고리즘이 필요한 경우 편집을 참조하십시오. – dcp

+0

감사합니다. –

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

답변 해 주셔서 감사합니다. 이것이 질문자의 문제를 해결하는 방법에 대한 설명을 추가하는 것을 고려하십시오. –