【问题标题】:Normalizing data with DISTINCT使用 DISTINCT 规范化数据
【发布时间】:2011-02-21 23:03:57
【问题描述】:

我的每台 PC 每月有 1,000,000 行由某些监控软件生成。 DataToImport(临时)表如下所示:

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)

..这样“事件”将有无数行,但它们非常小,因此数据库大小是可管理的,并且可以为查询性能索引表:

-- 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)实际上是一个复合键,因为这三个项目中的任何一个都可以变化,这代表一个唯一的条目。我需要提取 distinct 三元组来插入它们...

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

如何确保唯一的 File 行被规范化?

【问题讨论】:

    标签: sql normalization


    【解决方案1】:

    我会使用

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

    ...但我会先将其性能与 Quassnoi 的 SELECT...INTERSECT 解决方案进行比较。

    【讨论】:

    • +1,什么,希望我先发布它:)您可以删除DISTINCT:EXCEPT暗示它。
    • 您的回答速度提高了 40%。它还会处理 NULL 吗?
    【解决方案2】:
    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 的解决方案更优雅。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-07-07
      • 2018-09-20
      • 2016-12-06
      • 2011-01-21
      • 2020-07-31
      • 2012-06-01
      • 2016-07-23
      • 2020-01-04
      相关资源
      最近更新 更多