2009-07-10 70 views
3

我正在創建一個腳本,用於「合併」並從表中刪除重複行。該表包含地址信息,並使用整數字段將有關電子郵件的信息存儲爲位標誌(列名稱lngValue)。例如,lngValue & 1 == 1表示它的主要地址。更新列爲不同的聚合值

有兩次輸入同一封電子郵件的實例,但有時會使用不同的lngValues。爲了解決這個問題,我需要從所有重複項中取出lngValue,並將它們分配給一個倖存的記錄,並刪除剩餘的記錄。

迄今爲止我最大的頭痛是與記錄的「合併」。我想要做的是將重複記錄的所有lngValues合併在一起。這是迄今爲止我所知道的,它只能找到所有lngValues按位或者一起的值。

警告:亂碼提前

declare @duplicates table 
(
lngInternetPK int, 
lngContactFK int, 
lngValue int 
) 

insert into @duplicates (lngInternetPK, lngContactFK, lngValue) 
(
select tblminternet.lngInternetPK, tblminternet.lngContactFK, tblminternet.lngValue from tblminternet inner join 
(select strAddress, lngcontactfk, count(*) as count from tblminternet where lngValue & 256 <> 256 group by strAddress, lngcontactfk) secondemail 
On tblminternet.strAddress = secondemail.strAddress and 
tblminternet.lngcontactfk = secondemail.lngcontactfk 
where count > 1 and tblminternet.strAddress is not null and tblminternet.lngValue & 256 <> 256 --order by lngContactFK, strAddress 
) 

update @duplicates set lngValue = t.val 

from 
       (select (sum(dupes.lngValue) & 65535) as val from 
        (select here.lngInternetPK,      here.lngContactFK, here.lngValue from tblminternet here inner join 
        (select strAddress, lngcontactfk, count(*) as count from tblminternet where lngValue & 256 <> 256 group by strAddress, lngcontactfk) secondemail 
        On here.strAddress = secondemail.strAddress  and 
        here.lngcontactfk = secondemail.lngcontactfk 
        where count > 1 and here.strAddress is not  null and here.lngValue & 256 <> 256) dupes, tblminternet this 

       where this.lngContactFK = dupes.lngContactFK 
       ) t 
where lngInternetPK in (select lngInternetPK from @duplicates)  

編輯:
由於這裏要求是一些樣本數據:

表名:tblminternet
列名稱:
lngInternetPK
lngContactFK
lngValue
strAddress

實施例第1行:
lngInternetPK:1
lngContactFK:1
lngValue:33
strAddress: 「[email protected]

例行2:
lngInternetPK:2
lngContactFK :1
lngValue:40
strAddress:「[email protected]

如果這兩個在這裏合併是所期望的結果:
lngInternetPK:1
lngContactFK:1
lngValue:41
strAddress: 「[email protected]

其他必要的規則:
每個接觸可以有多個電子郵件,但每個電子郵件行必須是不同的(每個電子郵件只能顯示爲一行)。

+0

你可以分享一些樣本數據的任何機會呢?看看數據現在的樣子以及期望的結果可能有助於產生一些答案。 – 2009-07-11 21:05:07

+0

Griswold:已添加數據 – 2009-07-13 16:11:10

+0

感謝您發佈數據。它有幫助。 – 2009-07-13 16:49:40

回答

3

SQL Server缺乏原生按位聚集,這就是爲什麼我們要模仿他們。

這裏的主要思想是生成一組位從015,對每一位申請位掩碼的價值和選擇MAX(這將給我們對於給定的有點OR),然後選擇SUM(這將合併位掩碼)。

我們只是更新第一個lngInternetPK對於任何給定(lngContactFK, strValue)與新值lngValue,並刪除所有重複項。

;WITH bits AS 
     (
     SELECT 0 AS b 
     UNION ALL 
     SELECT b + 1 
     FROM bits 
     WHERE b < 15 
     ), 
     v AS 
     (
     SELECT i.*, 
       (
       SELECT SUM(value) 
       FROM (
         SELECT MAX(lngValue & POWER(2, b)) AS value 
         FROM tblmInternet ii 
         CROSS JOIN 
           bits 
         WHERE ii.lngContactFK = i.lngContactFK 
           AND ii.strAddress = i.strAddress 
         GROUP BY 
           b 
         ) q 
       ) AS lngNewValue 
     FROM (
       SELECT ii.*, ROW_NUMBER() OVER (PARTITION BY lngContactFK, strAddress ORDER BY lngInternetPK) AS rn 
       FROM tblmInternet ii 
       ) i 
     WHERE rn = 1 
     ) 
UPDATE v 
SET  lngValue = lngNewValue; 

;WITH v AS 
     (
     SELECT ii.*, ROW_NUMBER() OVER (PARTITION BY lngContactFK, strAddress ORDER BY lngInternetPK) AS rn 
     FROM tblmInternet ii 
     ) 
DELETE v 
WHERE rn > 1 

請參閱本文中我的博客更詳細的解釋:

0

我相信下面的查詢得到你想要的。該例程假定每個聯繫人最多有兩個重複地址。如果每個聯繫人有多個副本,則該查詢將不得不進行修改。我希望這有幫助。

Declare @tblminternet 
Table 
(lngInternetPK int, 
    lngContactFK int, 
    lngValue int, 
    strAddress varchar(255) 
) 

Insert Into @tblminternet 
select 1, 1, 33, '[email protected]' 
union 
select 2, 1, 40, '[email protected]' 
union 
select 3, 2, 33, '[email protected]' 
union 
select 4, 2, 40, '[email protected]' 
union 
select 5, 3, 2, '[email protected]' 

--Select * from @tblminternet 

Select Distinct 
    A.lngContactFK , 
    A.lngValue | B.lngValue as 'Bitwise OR', 
    A.strAddress 
From @tblminternet A, @tblminternet B 
Where A.lngContactFK = B.lngContactFK 
And A.strAddress = B.strAddress 
And A.lngInternetPK != B.lngInternetPK 
0

您可以在.NET中創建的SQL Server聚合函數,然後可以在SQL服務器在線執行。我認爲這需要最少的SQL Server 2005和Visual Studio 2010.我使用Visual Studio 2013 Community Edition(即使用於商業用途也是免費的)用於.NET 2和SQL Server 2005.

請參閱MSDN文章:https://msdn.microsoft.com/en-us/library/91e6taax(v=vs.90).aspx

首先,您需要啓用SQL Server中的CLR功能:https://msdn.microsoft.com/en-us/library/ms131048.aspx

sp_configure 'show advanced options', 1; 
GO 
RECONFIGURE; 
GO 
sp_configure 'clr enabled', 1; 
GO 
RECONFIGURE; 
GO 
  1. 創建SQL Server - > SQL Server數據庫項目
  2. 右鍵CLI CK的新項目,並選擇屬性
  3. 配置項目設置
  4. 配置下SQL CLR目標CLR語言(如Java)的新項目
  5. 右鍵單擊,然後選擇添加下,有針對性的SQL Server版本 - >新項...
  6. 當彈出對話框,選擇SQL Server - > SQL CLR VB - > SQL CLR VB總結

現在你可以在VB編寫的代碼按位:

Imports System 
Imports System.Data 
Imports System.Data.SqlClient 
Imports System.Data.SqlTypes 
Imports Microsoft.SqlServer.Server 


<Serializable()> _ 
<Microsoft.SqlServer.Server.SqlUserDefinedAggregate(Format.Native)> _ 
Public Structure AggregateBitwiseOR 

    Private CurrentAggregate As SqlTypes.SqlInt32 

    Public Sub Init() 
     CurrentAggregate = 0 
    End Sub 

    Public Sub Accumulate(ByVal value As SqlTypes.SqlInt32) 
     'Perform Bitwise OR against aggregate memory 
     CurrentAggregate = CurrentAggregate OR value 
    End Sub 

    Public Sub Merge(ByVal value as AggregateBitwiseOR) 
     Accumulate(value.Terminate()) 
    End Sub 

    Public Function Terminate() As SqlInt32 
     Return CurrentAggregate 
    End Function 

End Structure 

現在部署:https://msdn.microsoft.com/en-us/library/dahcx0ww(v=vs.90).aspx

  1. 構建使用菜單欄項目:建設 - >建設項目名(如果構建失敗,錯誤04018然後下載的數據工具的新版本@http://msdn.microsoft.com/en-US/data/hh297027或將菜單欄:工具 - >擴展和更新,然後在更新下選擇更新爲Microsoft SQL Server更新爲數據庫工具)
  2. 將編譯的DLL複製到C:\ Program Files \ Microsoft SQL Server \ MSSQL.1 \ MSSQL \ Binn和C:\
  3. 寄存器DLL:

    CREATE ASSEMBLY [CLRTools] FROM'c:CLRTools。DLL」 WITH PERMISSION_SET = SAFE

  4. 創建SQL骨料:。

    CREATE AGGREGATE [DBO] [AggregateBitwiseOR](@值INT) 返回int EXTERNAL NAME [CLRTools] [CLRTools.AggregateBitwiseOR] ;

如果你得到錯誤 「附近有語法錯誤 '外部'」,然後用下面的命令更改數據庫兼容級別:

對於SQL Server 2005:EXEC sp_dbcmptlevel的 '數據庫名稱',90

對於SQL Server 2008:EXEC sp_dbcmptlevel的 '數據庫名稱',100

  • 測試代碼:

    SELECT dbo.AggregateBitwiseOR(富)爲Foo從酒吧

  • 我發現這篇文章有幫助:http://www.codeproject.com/Articles/37377/SQL-Server-CLR-Functions