更新列是不同的聚合值(Update column to be different aggregate

2019-06-25 14:49发布

我创建一个脚本,对“合并”,并从表中删除重复的行。 表中包含的地址信息,并使用一个整数字段用于存储有关的电子邮件作为位标志(列名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: “me@myaddress.com”

例如第2行:
lngInternetPK:2
lngContactFK:1
lngValue:40
strAddress: “me@myaddress.com”

如果这两个在这里合并是理想的结果:
lngInternetPK:1
lngContactFK:1
lngValue:41
strAddress: “me@myaddress.com”

其他必要的规则:
每个联系人可以有多个电子邮件,但每个电子邮件行必须是不同(每个电子邮件只能出现一个行)。

Answer 1:

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

请参阅本文中我的博客更详细的解释:

  • SQL服务器:骨料位或


Answer 2:

我相信下面的查询得到你想要的东西。 这一程序假设每个接触的两个重复的地址的最大。 如果有接触的每一个以上DUP,查询将不得不进行修改。 我希望这有帮助。

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

Insert Into @tblminternet 
select 1, 1, 33, 'me@myaddress.com' 
union
select 2, 1, 40, 'me@myaddress.com'
union 
select 3, 2, 33, 'me@myaddress2.com'
union 
select 4, 2, 40, 'me@myaddress2.com'
union 
select 5, 3, 2, 'me@myaddress3.com'

--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


Answer 3:

您可以在.NET中创建的SQL Server聚合函数,然后可以在SQL服务器在线执行。 我想,这至少需要使用Visual Studio 2013社区版(甚至用于商业用途免费),与.NET 2和SQL Server 2005中使用SQL Server 2005和Visual Studio 2010年我做了一个。

请参阅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. 在新的项目,并选择属性右键单击
  3. 配置项目设置下,有针对性的SQL Server版本
  4. 配置下SQL CLR目标CLR语言(如Java)
  5. 在新的项目上右键单击,然后选择添加 - >新项...
  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)RETURNS INT EXTERNAL NAME [CLRTools] [CLRTools.AggregateBitwiseOR]。。

如果你得到错误“附近有语法错误‘外部’”,然后用下面的命令更改数据库兼容级别:

对于SQL Server 2005:EXEC sp_dbcmptlevel的 '数据库名称',90

对于SQL Server 2008:EXEC sp_dbcmptlevel的 '数据库名称',100

  1. 测试你的代码:

    选择dbo.AggregateBitwiseOR(富)为Foo FROM酒吧

我发现这篇文章有帮助: http://www.codeproject.com/Articles/37377/SQL-Server-CLR-Functions



文章来源: Update column to be different aggregate values