表中缺less数据

我有一个SQL挑战

我的数据提供商给我发送一个CSV格式的数据,如下面的例子现在,由于某种原因文件丢失的数据也许是为了节省空间,使表小,我不知道。

Field_1和Field_2中缺less数据。 数据出现在一个logging中,并且下列logging具有NULL值,直到下一个logging。 所以在下面的示例Field_1的第二个和第三个logging中的值应该是“ID_1”而不是NULL相同的Field_2的值应该是ABC而不是NULL

Field_1 Field_2 Field_3 ----------------------- ID_1 ABC Value_3 NULL NULL Value_3 --> ID_1 ABC Value_3 NULL NULL Value_3 --> ID_1 ABC Value_3 ID_2 CDE Value_3 NULL NULL Value_4 --> ID_2 CDE Value_4 ID_3 EFG Value_X 

到目前为止,我已经写了一个excel模块,在我导入数据之前修复了我的数据,但是这些文件将会变得非常大,而excel将无法处理这个问题。 所以我的select是使用TSQL游标,并执行一些将填写数据的过程。 或者我可以构build我的select查询来弥补缺失的数据,并在运行select数据之前生成填充数据的虚拟表

什么是最好的解决scheme呢? 我的要求是低维护和空间效率之间的快乐媒介我正在谈论17个缺失数据的领域和一个月约15万条logging。

感谢帮助

我猜你不能问你的数据提供商的另一种格式? 因为它似乎文件格式不正确。

将数据加载到数据库的两个基本规则:

  1. 不要混淆数据。 随着数据的交付,他们也应该加载。

  2. 可以在加载时添加数据,也可以更改表示。 例如,可以将行号或文件名添加为新列,并且可以将无用的"N/A""NULL"string更改为零长度string,从而在数据库中创buildNULL。 标准的Unix工具非常适合这个目的。 很多都可以在Windows上使用 。

另一个好的政策是:

  1. 不要使用游标。 如果你想使用游标,你正在考虑行。 想想集合。

在你的情况下,正如其他人所指出的那样,你如何为缺less值提供代理值的想法 – 通过使用“更早的”值 – 取决于知道CSV文件中出现的行的顺序。 在数据库理论中,这被称为数据中的隐含意义 。 在SQL中,我们只有明确的含义 :对于一行是“之前”,必须有一列进行比较。

所以:编号行,并加载NULL,可以这么说。

然后,您可以获得所需的信息以获得所需的效果:您可以将表格自行join,并将缺less的数据与相关的“早期”数据合并。 没有必要触发器或任何异国情调。 只要find最后的“好”行,并使用这些值代替丢失的。

 create table T (line, Field_1, Field_2, Field_3); insert into T values (1, 'ID_1', 'ABC', 'Value_3') , (2, NULL, NULL, 'Value_3') , (3, NULL, NULL, 'Value_3') , (4, 'ID_2', 'CDE', 'Value_3') , (5, NULL, NULL, 'Value_4') , (6, 'ID_3', 'EFG', 'Value_X'); create view vT as select a.line , coalesce(a.Field_1, b.Field_1) as Field_1 , coalesce(a.Field_2, b.Field_2) as Field_2 , a.Field_3 from T as a join T as b on b.line = ( -- last line before a.line with good values (unless a is good) select max(line) from T where line <= a.line and Field_1 is not NULL and Field_2 is not NULL ); select * from T; select * from vT; 

输出:

 line Field_1 Field_2 Field_3 ---------- ---------- ---------- ---------- 1 ID_1 ABC Value_3 2 Value_3 3 Value_3 4 ID_2 CDE Value_3 5 Value_4 6 ID_3 EFG Value_X line Field_1 Field_2 Field_3 ---------- ---------- ---------- ---------- 1 ID_1 ABC Value_3 2 ID_1 ABC Value_3 3 ID_1 ABC Value_3 4 ID_2 CDE Value_3 5 ID_2 CDE Value_4 6 ID_3 EFG Value_X 

coalesce函数接受一个列表并返回第一个非NULL值。 b行保证没有NULL; 一行可能不行。 如果a好,我们用这个,否则我们从b拿。

对不起,我不明白…

你说:

所以在下面的示例Field_1的第二个和第三个logging中的值应该是“ID_1”而不是NULL相同的Field_2的值应该是ABC而不是NULL

 Field_1 Field_2 Field_3 ----------------------- ID_1 ABC Value_3 NULL NULL Value_3 NULL NULL Value_3 ID_2 CDE Value_3 NULL NULL Value_4 ID_3 EFG Value_X 

如果我把你所说的话应用到桌子上,它会是这样的…

 Field_1 Field_2 Field_3 ----------------------- ID_1 ABC Value_3 ID_1 ABC Value_3 ID_1 ABC Value_3 ID_2 CDE Value_3 ID_2 CDE Value_4 ID_3 EFG Value_X 

因此,假设您需要副本数据,您可以将其导入到表中,然后创build一个存储过程,从完全填充的行复制数据,然后将其插入到具有相同Field_1标识的行中?

一个可能的方法来做到这一点。 但是,请找出您的表的真实顺序,并将ORDER BY (SELECT NULL)

 WITH cte AS ( SELECT *, ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) as row_num FROM YourTable ) SELECT Field_1 = ISNULL(Field_1,(SELECT TOP 1 Field_1 FROM cte c1 WHERE c1.Field_1 IS NOT NULL AND c1.row_num < c.row_num ORDER BY c1.row_num DESC)) ,Field_2 = ISNULL(Field_2,(SELECT TOP 1 Field_2 FROM cte c1 WHERE c1.Field_2 IS NOT NULL AND c1.row_num < c.row_num ORDER BY c1.row_num DESC)) ,Field_3 FROM cte c 

一张桌子没有固有的顺序。
即使是一个具有聚类PK的表也没有被sorting。
在没有订单条款的情况下,没有保证订单的select

因此,如果您要在SQL中修复数据,则需要使用身份插入,以便重新生成订单。

我会更新数据,所以你只需要做一次
select查找上面的数据是一个相当昂贵的查询

这只是一行一列,但是这是一个开始

 update tableTarget set tableTarget.Field_1 = tableSource.Field_1 from table as tableTarget join table as tableSource on tableTarget.Iden = tableSource.Iden + 1 and tableTarget.Field_1 is null and tableSource.Field_1 is not null 

现在这个只能做一对,所以如果你连续有4个空值,那么你需要运行4次
运行它,直到说零行更新
但是你可以有数百次连续的4个空值,而且只需要运行4次

我知道多次运行相同的更新看起来像一个麻烦,但它是一个非常有效的更新
根据样本数据,只有less数几个空值

这没有经过testing
效率不高,但只需要为每列运行一次

 update tableTarget set tableTarget.Field_1 = (select top 1 tableSource.Field_1 from table as tableSource where tableSource.Field_1 is not null and tableSource.Iden < tableTarget.iden order by tableSource.Iden desc ) from table as tableSource where tableTarget.Field_1 is null 

我尝试了所有这些查询,他们都工作。 这是说,他们需要永远完成我能够做到这一点与Excel 10倍更快

我很好奇,如果使用CURSOR来完成这个任务不会更快