映射列而不知道表中的内容

问题描述 投票:1回答:1

我有一个奇怪的情况,我将有来自各种来源的数据(所有平面文件,没有一个在我的控制,无论我多少次要求标准格式,我得到不同的列标题和不同的列顺序) 。我们没有人力来手动浏览这些文件来确定哪些列很重要。每个平面文件将包含两到六个“标识”列。但是,某些列不是唯一的,但它们的组合可以形成唯一的键。总而言之,每个平面文件可以有大约一百列。

因此,最初,我计划将数据加载到临时表中,并要求用户确定哪些列包含哪些数据。一旦我知道,我可以毫无问题地处理文件。我将有两到六列来识别与现有记录的匹配以及我应该收集的其他数据(所有这些都由用户识别)。

然后我被要求添加系统“推荐”哪些数据列的能力。为此,我的计划是一个计数。我会计算每列有多少非空值,然后计算这些非空值中有多少与六个可能列中的每一列相匹配。从那里,我可以采用一个简单的比率来确定所包含的数据是否属于该特定类型的可能性。会有一些高估的列不是唯一的,但总的来说,它工作得很好。问题是它很慢。

我创建了一个元数据表,我调用的是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

有更快的方法吗?

sql-server tsql query-performance
1个回答
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
...
)
© www.soinside.com 2019 - 2024. All rights reserved.