Estou importando e limpando dados de uma fonte de dados que possui registros como este:
Os dados precisam ser classificados e reorganizados com base no tipo de evento.
O esquema de destino seria algo como isto:
Create Table dbo.Destination
(
DestinationId int not Null primary key clustered,
EventType int not null,
fkyCustomerId int not null,
Constraint FK_Destination_Customers References dbo.Customers (pkyCustomerId),
fkyCategoryId int not null
Constraint FK_Destination_Categories References dbo.Categories (pkyCategoryId),
fkyCompanyId int not null
Constraint FK_Destination_Companies References dbo.Companies(pkyCompanyId),
fkyLocationId int not null
Constraint FK_Destination_Locations References dbo.Locations(pkyLocationId),
Amount money not null
Constraint DF_Destination_Amount Default(0)
)
-- Lookup table
Create Table dbo.Categories
(
pkyCategoryId int not null primary key clustered,
SourceCategoryId char(10) Not Null,
CategoryName varchar(50) Not Null
)
-- Lookup table
Create Table dbo.Companies
(
pkyCompanyId int not null primary key clustered,
SourceCompanyId varchar(10) Not null,
CompanyName varchar(50) Not Null
)
-- Lookup Table
Create Table dbo.Locations
(
pkyLocationId int not null primary key clustered,
SourceLocationId varchar(10) Not Null,
LocationName varchar(50) Not Null
)
Para cada tipo de evento, e pode haver centenas de tipos de eventos, existem regras sobre quais dados existem em cada uma das col
colunas.
Portanto, para o tipo de evento 1234, Col0
tem o mapeamento para a Categories
pesquisa e Col1
o mapeamento para a Companies
pesquisa.
No entanto, para Event Type 5000, Col0
contém o mapeamento para a Companies
pesquisa e Col1
contém o mapeamento para Locations
.
Além disso, há situações em que haverá valores nulos para todas as Col
colunas, o que significa que preciso mapeá-los para valores padrão de categoria, empresa etc.
Preciso criar um processo de importação que possa manipular as regras existentes e as novas regras em potencial. A importação processará aproximadamente 2,5 milhões de linhas por dia e aumentará.
Qual seria uma boa forma de implementar esse tipo de importação. Nada é imutável aqui, além dos dados de origem, por isso estou mais do que disposto a considerar a ideia de alterar o esquema, etc.
O objetivo final é transformar os dados de origem para que possam ser facilmente usados para fins de relatório.
Acho que o maior desafio será fazer as transformações de tipo de evento com eficiência, então vou me concentrar nisso e ignorar completamente o esquema.
Meu primeiro pensamento (leia-se: na verdade, nunca tentei isso) é usar SQL dinâmico para criar uma
SELECT
instrução que fará a transformação de dados de forma que os valores terminem em suas colunas corretas (ou seja,Col0
-->CompanyId
ou qualquer outra coisa). Isso se resume a uma tabela de mapeamento que consiste no tipo de evento, na coluna de origem, na coluna de destino e em um valor padrão, se necessário.Uma vez que você tenha a tabela de mapeamento (ou table s , dependendo de quão complexa ela realmente é), você pode usá-la para construir dinamicamente uma instrução SQL no formato:
Crie a instrução como parte do processo ETL. Se você precisar adicionar um novo tipo de evento, basta adicionar os mapeamentos de coluna necessários à tabela de mapeamento e eles serão manipulados na próxima vez que o processo ETL for executado.
Depois que os dados de origem estiverem nesse tipo de estado, o restante do processo de importação deve ser bastante padrão.
OK, então, depois de um pouco de pôquer, finalmente cheguei a esta solução.
Eu criei uma tabela de mapeamento como esta:
E então, para cada tipo de evento, preencha a tabela de mapeamento com os valores relevantes.
Por exemplo, se a categoria estivesse presente, o
IsCategoryPresent
valor seria1
, oCategoryLocation
valor seriaCol2
e oCategoryDefault
valor seria1
.O valor CategoryLocation corresponde à coluna na tabela de origem e o valor CategoryDefault corresponde ao valor padrão usado na nova tabela de pesquisa.
Se a categoria não estiver presente, o
IsCategoryPresent
valor será0
, oCategoryLocation
valor seráSourceTableId
e oCategoryDefault
valor será1
. Eu tenho que definir o local para uma coluna válida no SourceTable ou o SQL Server gera um erro.O SQL que tenho agora é este procedimento armazenado (que executo para cada tipo de evento na tabela de mapeamento).
Estou ingressando nas tabelas de pesquisa e, em seguida, usando uma
case
instrução junto com o SQL dinâmico para determinar qual coluna usar. Portanto, se um valor estiver presente, escolho a coluna da tabela de origem. Se um valor não estiver presente, eu uso um valor padrão que garante que eu sempre obtenha um valor FK para inserir em minha tabela de destino.Você também notará que eu também tenho esse cheque em minha junção
Len(IsNull(re.' + rem.CompanyLocation + ', space(0))) = 0
Isso ocorre porque descobri que algumas colunas não eram valores nulos, mas em branco. O que me causou um pouco de dor também.
Eu tenho executado isso por alguns dias e parece funcionar muito bem.
Dito isto, qualquer comentário seria muito apreciado!