【问题标题】:Merging two tables合并两个表
【发布时间】:2009-07-31 18:55:06
【问题描述】:

我有两个包含以下列的表(两个表中的列相同):

  1. 函数名,
  2. 频率计数

我想将这两个表合并成一个带有列的最终表:

  1. 函数名称
  2. 基本频率计数
  3. 比较频率计数
  4. 频率计数增量

合并操作应该如下发生:

  • 如果 [FunctionName] 在 Table1 中而不在 Table2 中,

    [Base Frequency Count] = Table1.[FrequencyCount]
    [Compared Frequency Count] = 0
    [Delta of Frequency Count] = Table1.[FrequencyCount]
    
  • 如果 [FunctionName] 在 Table2 中而不在 Table1 中,

    [Base Frequency Count] = 0         
    [Compared Frequency Count] = Table2.[FrequencyCount]
    [Delta of Frequency Count] = Table2.[FrequencyCount]
    
  • 如果 [FunctionName] 同时在 Table1 和 Table2 中,

    [Base Frequency Count] = Table1.[FrequencyCount]         
    [Compared Frequency Count] = Table2.[FrequencyCount]
    [Delta of Frequency Count] = Table1.[FrequencyCount]-Table2.[FrequencyCount]
    

希望查询具有良好的性能和最小的数量。的连接。 如果有人能给出好的指点,那就太好了。

【问题讨论】:

    标签: sql sql-server sql-server-2005


    【解决方案1】:
    SELECT ISNULL(fn.FunctionName, fc.FunctionName) AS FunctionName, 
           ISNULL(fn.FrequencyCount, 0) AS BaseFrequency,
           ISNULL(fc.FrequencyCount, 0) AS ComparedFrequencyCount,
           COALESCE((fn.FrequencyCount - fc.FrequencyCount), fn.FrequencyCount, fc.FrequencyCount) AS DeltaOfFrequencyCount
    INTO FinalTable
    FROM FunctionName fn FULL OUTER JOIN FrequencyCount fc ON fn.FunctionName = fc.FunctionName
    

    请注意,如果 fn.FrequencyCount 或 fc.FrequencyCount 为 null(在 SQL 中,值 - null = null),COALESCE 将导致第一个表达式中的 null (移动到链中的下一个)。

    【讨论】:

    • 现在我想起来了,CASE 语句也可以去掉,用 ISNULL 代替。
    【解决方案2】:
    SELECT *
      INTO new_table_name 
      FROM (SELECT t.frequencycount 'Base Frequency Count',
                   0 'Compared Frequency Count',
                   t.frequencycount 'Delta of Frequency Count'
              FROM TABLE1 t
              JOIN TABLE2 t2 ON t2.functionname != t.functionname
            UNION
            SELECT 0 'Base Frequency Count',
                   t2.frequencycount 'Compared Frequency Count',
                   t2.frequencycount 'Delta of Frequency Count'
              FROM TABLE2 t2
              JOIN TABLE1 t ON t.functionname != t2.functionname
            UNION
            SELECT t.frequencycount 'Base Frequency Count',
                   t2.frequencycount 'Compared Frequency Count',
                   t.frequencycount - t2.frequencycount 'Delta of Frequency Count'
              FROM TABLE1 t
              JOIN TABLE2 t2 ON t.functionname = t2.functionname)
    

    【讨论】:

    • 太完美了!感谢您的答复。但是在执行这个查询时我注意到了一个问题。当我在结果表 (new_table_name) 中包含“函数名称”时,执行查询大约需要 1.49 分钟,而未选择“函数名称”时需要 0.3 秒。上面有什么cmets吗?
    • 您复制的两个表中的 FunctionName 是否有索引?
    • 您将索引与唯一约束混合在一起。如果您在 functionName 列上指定索引,您应该会看到时间有所改善。
    • 感谢您的及时回复。是的,你是对的。 [Function Name] 列的数据类型为 nvarchar(max),它限制了 [Function Name] 上的索引规范。有什么选择吗?
    • 不客气。但我确认您可以将索引应用于 nvarchar(max) 列。请参阅此处的性能注意事项部分:msdn.microsoft.com/en-us/library/ms190806(SQL.90).aspx
    【解决方案3】:

    不确定这是否会比 rexem 的解决方案慢(我没有对其进行基准测试)。但这对您来说可能更容易阅读。通过基于主键而不是 FunctionName 进行选择也可以显着提高性能。

    --TABLE 1
    SELECT FunctionName, FrequencyCount AS Base, 0 AS Compared, FrequencyCount AS Delta
    FROM TableOne
    WHERE FunctionName NOT IN (SELECT FunctionName FROM TableTwo)
    UNION
    
    --TABLE 2
    SELECT FunctionName, 0 AS Base, FrequencyCount AS Compared, FrequencyCount AS Delta
    FROM TableTwo
    WHERE FunctionName NOT IN (SELECT FunctionName FROM TableOne)
    UNION
    
    --DELTA
    SELECT FunctionName, 
    (SELECT FrequencyCount FROM TableOne WHERE FunctionName = DeltaTable.FunctionName) AS Base,
    (SELECT FrequencyCount FROM TableTwo WHERE FunctionName = DeltaTable.FunctionName) AS Compared,
    (SELECT FrequencyCount FROM TableOne WHERE FunctionName = DeltaTable.FunctionName) - (SELECT FrequencyCount FROM TableTwo WHERE FunctionName = DeltaTable.FunctionName) AS Delta
    FROM TableOne DeltaTable
    WHERE FunctionName IN (SELECT FunctionName FROM TableOne)
    AND FunctionName IN (SELECT FunctionName FROM TableTwo)
    

    修正三角洲

    --DELTA
    SELECT One.FunctionName, 
    One.FrequencyCount AS Base,
    Two.FrequencyCount AS Compared,
    One.FrequencyCount - Two.FrequencyCount AS Delta
    FROM TableOne One
    INNER JOIN TableTwo Two
        ON One.FunctionName = Two.FunctionName
    

    【讨论】:

    • SELECT 子句中的子查询将成为性能噩梦——它们会针对结果集中的每条记录执行。据说 IN 子句的运行速度比使用 EXISTS 慢(可以说它比使用 JOIN 运行速度慢)。
    • Delta 可以更改为:--DELTA SELECT One.FunctionName, One.FrequencyCount AS Base, Two.FrequencyCount AS Compare, One.FrequencyCount - Two.FrequencyCount AS Delta FROM TableOne One INNER JOIN TableTwo两个 ON One.FunctionName = Two.FunctionName 这将消除子选择...更接近您的连接解决方​​案。如果表上有正确的索引,Atul 不必担心。
    猜你喜欢
    • 2014-03-19
    • 1970-01-01
    • 1970-01-01
    • 2021-02-26
    • 2012-02-23
    • 2011-04-11
    相关资源
    最近更新 更多