如何使用 SSIS 从平面文件中删除重复的行?

Posted

技术标签:

【中文标题】如何使用 SSIS 从平面文件中删除重复的行?【英文标题】:How to remove duplicate rows from flat file using SSIS? 【发布时间】:2010-09-14 03:01:24 【问题描述】:

首先我要说的是,能够从一个平面文件中获取 1700 万条记录,然后将其推送到远程机器上的数据库并花费 7 分钟,这真是太棒了。 SSIS 真的很棒。但是现在我已经有了这些数据,我该如何删除重复项?

更好的是,我想获取平面文件,从平面文件中删除重复项并将它们放回另一个平面文件中。

我正在考虑一个:

Data Flow Task

文件源(带有关联的文件连接) for 循环容器 一个脚本容器,其中包含一些逻辑来判断另一行是否存在

谢谢,这个网站上的每个人都知识渊博。

Update: I have found this link, might help in answering this question

【问题讨论】:

当您说“重复”时,您是指相同的记录,还是主键相同的记录? 【参考方案1】:

使用排序组件。

只需选择您希望对加载的行进行排序的字段,在左下角您会看到一个用于删除重复项的复选框。此框仅根据排序标准删除任何重复的行 所以在下面的例子中,如果我们只对第一个字段进行排序,这些行将被认为是重复的:

1 | sample A |
1 | sample B |

【讨论】:

【参考方案2】:

我建议使用 SSIS 将记录复制到临时表中,然后根据您的情况创建一个使用 Select Distinct 或 Rank 的任务,以选择将它们汇集到平面文件中的重复项并从临时表中删除它们.最后一步是将临时表中的记录复制到目标表中。

确定重复是 SQL 擅长的,但平面文件不太适合。在您建议的情况下,脚本容器将加载一行,然后必须将其与 1700 万条记录进行比较,然后加载下一行并重复......性能可能不是那么好。

【讨论】:

【参考方案3】:

平面文件源 --> 聚合(您想要唯一的按列分组) --> 平面文件目标

【讨论】:

【参考方案4】:

策略通常取决于临时表有多少列。列越多,解越复杂。您链接的文章有一些非常好的建议。

到目前为止,我要补充到其他人所说的唯一内容是,具有日期和日期时间值的列将提供适合此处介绍的一些解决方案。

我想出的一个解决方案是:

SET NOCOUNT ON

DECLARE @email varchar(100)

SET @email = ''

SET @emailid = (SELECT min(email) from StagingTable WITH (NOLOCK) WHERE email > @email)

WHILE @emailid IS NOT NULL
BEGIN

    -- Do INSERT statement based on the email
    INSERT StagingTable2 (Email)
    FROM StagingTable WITH (NOLOCK) 
    WHERE email = @email

    SET @emailid = (SELECT min(email) from StagingTable WITH (NOLOCK) WHERE email > @email)

END

在进行重复数据删除时,这比 CURSOR 快很多,并且不会与服务器的 CPU 挂钩。要使用它,请将来自文本文件的每一列分隔到它们自己的变量中。在循环之前和内部使用单独的 SELECT 语句,然后将它们包含在 INSERT 语句中。这对我来说非常有效。

【讨论】:

Hector,在这次 SSIS 工作中,你将成为我的救星!非常感谢! 很高兴为您服务。 ;)【参考方案5】:

为了对平面文件执行此操作,我使用了 unix 命令行工具,排序:

sort -u inputfile > outputfile

不幸的是,windows 排序命令没有唯一选项,但您可以尝试从以下之一下载排序实用程序:

http://unxutils.sourceforge.net/ http://www.highend3d.com/downloads/tools/os_utils/76.html

(我还没有尝试过,所以恐怕不能保证)。

另一方面,要在记录加载到数据库时执行此操作,您可以使用 ignore_dup_key 在数据库表的键上创建唯一索引。这将使记录在加载时非常有效地唯一。

CREATE UNIQUE INDEX idx1 ON TABLE (col1, col2, ...) WITH IGNORE_DUP_KEY

【讨论】:

【参考方案6】:

我们可以为此使用查找表。就像 SSIS 提供了两种 DFS(数据流转换),即模糊分组和模糊查找。

【讨论】:

【参考方案7】:

有点肮脏的解决方案是使用跨越所有列的复合键设置目标表。这将保证明显的唯一性。然后在数据目标形状上,将任务配置为忽略错误。所有重复的插入都会被遗忘。

【讨论】:

【参考方案8】:

发现此页面link text 可能值得一看,虽然有 1700 万条记录可能需要一点时间

【讨论】:

【参考方案9】:

我建议在目标服务器上加载临时表,然后将结果合并到目标服务器上的目标表中。如果您需要运行任何卫生规则,那么您可以通过存储过程来执行此操作,因为您一定会获得比通过 SSIS 数据流转换任务更好的性能。此外,重复数据删除通常是一个多步骤的过程。您可能希望对以下内容进行重复数据删除:

    清晰的线条。 不同的列组,例如名字、姓氏、电子邮件地址等。 您可能希望对现有目标表进行重复数据删除。如果是这种情况,那么您可能需要包含 NOT EXISTS 或 NOT IN 语句。或者您可能希望使用新值更新原始行。这通常最好使用 MERGE 语句和源子查询。 获取特定模式的第一行或最后一行。例如,您可能希望在文件中为每次出现的电子邮件地址或电话号码输入最后一行。我通常依靠带有 ROW_NUMBER() 的 CTE 来生成顺序列和逆序列,如下例所示:

.

WITH    
    sample_records 
    (       email_address
        ,   entry_date
        ,   row_identifier
    )
    AS
    (
            SELECT      'tester@test.com'
                    ,   '2009-10-08 10:00:00'
                    ,   1
        UNION ALL

            SELECT      'tester@test.com'
                    ,   '2009-10-08 10:00:01'
                    ,   2

        UNION ALL

            SELECT      'tester@test.com'
                    ,   '2009-10-08 10:00:02'
                    ,   3

        UNION ALL

            SELECT      'the_other_test@test.com'
                    ,   '2009-10-08 10:00:00'
                    ,   4

        UNION ALL

            SELECT      'the_other_test@test.com'
                    ,   '2009-10-08 10:00:00'
                    ,   5
    )
,   filter_records 
    (       email_address
        ,   entry_date
        ,   row_identifier
        ,   sequential_order
        ,   reverse_order
    )
    AS
    (
        SELECT  email_address
            ,   entry_date
            ,   row_identifier
            ,   'sequential_order'  = ROW_NUMBER() OVER (
                                        PARTITION BY    email_address 
                                        ORDER BY        row_identifier ASC)
            ,   'reverse_order'     = ROW_NUMBER() OVER (
                                        PARTITION BY    email_address
                                        ORDER BY        row_identifier DESC)
        FROM    sample_records
    )
    SELECT      email_address
            ,   entry_date
            ,   row_identifier
    FROM        filter_records
    WHERE       reverse_order = 1
    ORDER BY    email_address;

在重复文件删除方面有很多选项可供您选择,但最终我建议您在目标服务器上加载临时表后在存储过程中处理此问题。清理数据后,您可以 MERGE 或 INSERT 到最终目的地。

【讨论】:

以上是关于如何使用 SSIS 从平面文件中删除重复的行?的主要内容,如果未能解决你的问题,请参考以下文章

SSIS - 如何从平面文件插入到具有日期范围的OLE DB?

防止平面文件目标中的重复标题 - SSIS

如何在 SSIS 中使用空格作为分隔符从平面文件中插入数据?

使用SSIS从SQL Server 2005中的平面文件导入时如何保留NULL值

SSIS - 删除现有行然后插入,不完整的结果

如何从文本文件中删除重复并包含某些单词的行?