我有一种奇怪的情况,我将有来自各种来源的数据(所有平面文件,这些都不在我的控制之下,无论我要求标准格式有多少次,我都会得到不同的列标题和不同的列顺序)。我们没有人力手动检查这些文件来确定哪些列很重要。每个平面文件将具有两到六个“标识”列。但是,某些列不是单独的,但它们的组合可以形成唯一的键。总而言之,每个平面文件可以有大约一百列。
因此,最初,我计划将数据加载到临时表中,并要求用户确定哪些列包含哪些数据。知道这一点后,就可以处理文件了。我将有两到六列来标识与现有记录和我应该收集的其他数据(均由用户标识)的匹配项。
然后,我被要求添加系统“推荐”哪些数据列的功能。为此,我的计划很重要。我将计算每列有多少个非空值,然后计算与六个可能的列中的每一个相匹配的那些非空值。从那里,我可以采用一个简单的比率来确定所包含的数据属于该特定类型的可能性。某些列的值可能会被高估,这些列不是唯一的,但总的来说,它运行良好。问题是它非常慢。
我创建了一个元数据表,我正在调用UploadedTableColumn,其中包含源文件的每个列标题以及它在数据库中映射到的列。这是我用来更新计数的存储过程:
CREATE PROCEDURE stored_Procedure
@FileLoadID INT
AS
BEGIN
DECLARE @SqlCommand NVARCHAR(MAX)
DECLARE the_cursor CURSOR FAST_FORWARD FOR
SELECT N'UPDATE UploadedTableColumn SET NumberNonemptyRows = (SELECT COUNT(*) FROM ' + DestinationTableName + N' WHERE ISNULL(' + DestinationColumnName + N','''') <> ''''),' + CHAR(13)
+ N'NumberID1Rows = (SELECT COUNT(*) FROM ' + DestinationTableName + N' WHERE ISNULL(' + DestinationColumnName + N','''') IN (SELECT ID1 FROM ID1Table) AND ISNULL(' + DestinationColumnName + N','''') <> ''''),' + CHAR(13)
+ N'NumberID2Rows = (SELECT COUNT(*) FROM ' + DestinationTableName + N' WHERE ISNULL(' + DestinationColumnName + N','''') IN (SELECT ID2 FROM ID2Table) AND ISNULL(' + DestinationColumnName + N','''') <> ''''),' + CHAR(13)
+ N'NumberIDDateRows = (SELECT COUNT(*) FROM ' + DestinationTableName + N' WHERE IIF(ISDATE(' + DestinationColumnName + N')=1,IIF(CAST(' + DestinationColumnName + N' AS DATE) IN (SELECT IDDate FROM IDDateTable),1,0),0) = 1 AND ISNULL(' + DestinationColumnName + N','''') <> ''''),' + CHAR(13)
+ N'NumberID4Rows = (SELECT COUNT(*) FROM ' + DestinationTableName + N' WHERE ISNULL(' + DestinationColumnName + N', '''') IN (SELECT ID4 FROM ID4Table) AND ISNULL(' + DestinationColumnName + N','''') <> ''''),' + CHAR(13)
+ N'NumberID5Rows = (SELECT COUNT(*) FROM ' + DestinationTableName + N' WHERE ISNULL(' + DestinationColumnName + N', '''') IN (SELECT ID5 FROM ID5Table) AND ISNULL(' + DestinationColumnName + N','''') <> ''''),' + CHAR(13)
+ N'NumberID6Rows = (SELECT COUNT(*) FROM ' + DestinationTableName + N' WHERE ISNULL(' + DestinationColumnName + N', '''') IN (SELECT ID6 FROM ID6Table) AND ISNULL(' + DestinationColumnName + N','''') <> '''')' + CHAR(13)
+ N'WHERE DestinationTableName = ''' + DestinationTableName + N''' AND DestinationColumnName = ''' + DestinationColumnName + N''' AND FileLoadID = ' + CAST(@FileLoadID AS NVARCHAR) + N';' + CHAR(13) As SqlCommand
FROM UploadedTableColumn
WHERE FileLoadID = @FileLoadID
OPEN the_cursor
FETCH NEXT FROM the_cursor
INTO @SqlCommand
WHILE @@FETCH_STATUS = 0
BEGIN
EXECUTE(@SqlCommand)
FETCH NEXT FROM the_cursor
INTO @SqlCommand
END
CLOSE the_cursor
DEALLOCATE the_cursor
END
有更快的方法吗?
答案 0 :(得分:1)
可能会有所帮助的小变化。
您说您将源表的每一列都保存在UploadedTableColumn中-不需要这样做,您的光标在许多不必要的列中循环。您可以通过抢先的列名匹配来消除很多内容。
因此,请从ID1Table,ID2Table等中获取所有可能的ID列的组合列表,然后仅将与DestinationTableName中的列实际匹配的列拉入UploadedTableColumn。
基于您的源数据中可能不超过6列具有匹配ID列名称的列,您现在仅检查这些列,而不是全部检查100 +。
当然,如果有人发送的数据没有标题且没有约定的格式,那么这对您没有帮助。
获得所需列的伪代码:
SELECT name
FROM sys.columns
WHERE [object_id] = OBJECT_ID('DestinationTableName')
AND Name IN
(
SELECT ID1 AS IDColumn FROM ID1Table
UNION ALL
SELECT ID2 AS IDColumn FROM ID2Table
...
)