2010-05-20 2 views
2

У меня есть 1 000 000 строк в месяц на ПК, созданный с помощью некоторого программного обеспечения для мониторинга. (Временная) таблица DataToImport выглядит следующим образом:Нормализация данных с помощью DISTINCT

EventID int   NOT NULL (Primary Key of denormalized table) 
EventType int   NOT NULL -- A enumerated value 
Computer nvarchar(50) NOT NULL -- Usually computer name 
When  DateTime  NOT NULL 
FileRef int   NOT NULL -- File generators reference 
FileDesc nvarchar(100) NOT NULL -- Humanly-readable description 
FilePath nvarchar(100) NOT NULL -- Relative Path on disk 

Я пытаюсь нормализовать эти данные в нескольких таблиц:

Computer (UniqueID, Name) 
File  (UniqueID, FileRef, FileDesc, FilePath) 
Event (ID, Type, ComputerUniqueID, When, FileUniqueID) 

..such, что «событие» будет иметь мильон строки, но они «повторно довольно мало, поэтому размер базы данных является управляемым и таблицы могут быть проиндексированы для выполнения запроса:

-- Grab new computers 
INSERT INTO Computer 
SELECT [Computer] AS [Name] 
FROM [DataToImport] 
WHERE [DataToImport].[Computer] NOT IN (SELECT [Name] FROM [Computer]) 

-- Grab new files 
INSERT INTO File 
SELECT [FileRef], [FileDesc], [FilePath] 
FROM [DataToImport] 
WHERE [FileRef] NOT IN (SELECT [FileRef] FROM File) 

-- Normalize rows 
INSERT INTO Event 
SELECT [EventID], [EventType], [Computer].[UniqueID], [File].[UniqueID] 
FROM [DataToImport] 
    INNER JOIN [Computer] ON [DataToImport].[Computer] = [Computer].[Name] 
    INNER JOIN [File] ON [DataToImport].[FileRef] = [File].[FileRef] 

.. это все выглядит замечательно, за исключением того, что триплет (FileRef, FileDesc, FilePath) действительно составной ключ, поскольку любой из трех элементов может меняться, и это представляет собой уникальную запись. Мне нужно извлечь различные тройни, чтобы вставить их ...

-- Grab new distinct files 
INSERT INTO File 
SELECT DISTINCT [FileRef], [FileDesc], [FilePath] 
FROM [DataToImport] 
WHERE [FileRef] NOT IN (errrrr....help!) 

Как я могу гарантировать, что уникальные строки файла нормированы?

ответ

3

Я хотел бы использовать

INSERT [File] ([FileRef], [FileDesc], [FilePath]) 
select distinct [FileRef], [FileDesc], [FilePath] 
    from [DataToImport] 
except select [FileRef], [FileDesc], [FilePath] 
    from [File] 

... но я бы сравнить его производительность с раствором SELECT ... INTERSECT Quassnoi первым.

+0

+1, что, пожелал, я отправил его первым :) Вы можете удалить 'DISTINCT':' EXCEPT' подразумевает это. – Quassnoi

+0

Ваш ответ на 40% быстрее. Будет ли он также обрабатывать NULL? – JBRWilkinson

+0

@ JBRW: да, будет. – Quassnoi

3
INSERT 
INTO File 
SELECT DISTINCT [FileRef], [FileDesc], [FilePath] 
FROM [DataToImport] di 
WHERE NOT EXISTS 
     (
     SELECT di.FileRef, di.FileDesc, di.FilePath 
     INTERSECT 
     SELECT FileRef, FileDesc, FilePath 
     FROM File 
     ) 

Это не важно в вашем случае, но это также будет обрабатывать NULL значения, как DISTINCT правильно, если столбцы были обнуляемыми.

@Philip Kelley решение более элегантное.

+1

+1 для хорошего спортивного мастерства! – JBRWilkinson