【问题标题】:Compound entries with different dates using SQL使用 SQL 的具有不同日期的复合条目
【发布时间】:2011-02-09 12:47:02
【问题描述】:

我必须将历史关税数据从一个大文本文件读入数据库,但数据有点混乱。

关税由typemeasure(实际费率和生效日期)组成

type 由类型代码和描述定义。 措施包含费率、适用的地理区域、费率以及开始日期和结束日期。

问题是同一关税有多个条目,具有不同的生效日期,需要复合到一个条目中。

文本文件如下所示:

(TypeCode、Area、Rate、StartDate、EndDate、描述)
1: 01021000#GEN #FREE #20050101#20061231#纯种动物#
2: 01021000#GEN #FREE #20070101#20071231#纯种动物#
3:01021000#GEN #FREE #20080101#99999999#纯种动物#
4:01029000#GEN #00000040.000% #20050101#20061231#OTHER #
5: 01029000#GEN #00000040.000% #20070101#20071231#OTHER #
6: 01029000#GEN #00000030.000% #20080101#20091231#OTHER #
7: 01029000#EU #00000030.000% #20070101#20071231#OTHER #

在这个例子中:

  • 1、2、3需要复合 与第一个措施合二为一 开始日期和最后结束日期 (01021000#GEN #FREE #20050101#99999999#纯种繁殖动物#)
  • 4、5需要复合为1 以第一个开始日期测量 最后结束日期(01029000#GEN #00000040.000% #20050101#20071231#OTHER #)
  • 6 必须保持独立,因为它有一个 不同的费率
  • 7 必须保持独立,因为它是 来自不同的地理区域

我正在使用 c# 和 Sql 精简版。我已经让它大部分工作,但它非常慢......目前必须有一种更有效的方法来做到这一点,在我的英特尔 i3 笔记本电脑上大约需要 40 分钟(66000 个条目)

我已经写下了我的步骤并给出了复合部分的代码。我还需要检查日期是否是后续日期。

步骤:
逐行读取文本文件
将行拆分为标记
将唯一的 TypeCode 及其描述插入 Type
使用以下代码将值插入到 Measure 表中:

// check to see if a measure with the same typecode, area and rate has already been inserted
String select = string.Format("SELECT TypeCode FROM Measure WHERE TypeCode = '{0}' AND AreaCode = '{1}' AND Rate = '{2}'", tokens[1], tokens[3], tokens[4]);//string.Format("SELECT TypeCode FROM Measure WHERE TypeCode = '{0}'", tokens[1]);
SqlCeDataAdapter adapter = new SqlCeDataAdapter(select, con);
DataTable table = new DataTable(); // Use DataAdapter to fill DataTable
adapter.Fill(table);

// if there are no similar records insert this one
if (table.Rows.Count <= 0)
{
    string insert = "INSERT INTO Measure VALUES (@TypeCode, @UOM, @AreaCode, @Rate, @StartDate, @EndDate)";
    SqlCeCommand com = new SqlCeCommand(insert, con);

    com.Parameters.AddWithValue("@TypeCode", tokens[1]);
    com.Parameters.AddWithValue("@UOM", tokens[2]);
    com.Parameters.AddWithValue("@AreaCode", tokens[3]);
    com.Parameters.AddWithValue("@Rate", tokens[4]);
    com.Parameters.AddWithValue("@StartDate", tokens[5]);
    com.Parameters.AddWithValue("@EndDate", tokens[6]);

    com.ExecuteNonQuery();
}
else
{
    // update the current record with the new enddate
    string update = "UPDATE Measure SET EndDate = @EndDate WHERE TypeCode = @TypeCode AND AreaCode = @AreaCode AND Rate = @Rate";
    SqlCeCommand com = new SqlCeCommand(update, con);

    com.Parameters.AddWithValue("@EndDate", tokens[6]);
    com.Parameters.AddWithValue("@TypeCode", tokens[1]);
    com.Parameters.AddWithValue("@AreaCode", tokens[3]);
    com.Parameters.AddWithValue("@Rate", tokens[4]);

    com.ExecuteNonQuery();
}

任何帮助或建议将不胜感激!

【问题讨论】:

    标签: c# sql database


    【解决方案1】:

    如果您使用的是 SQL Server 2008 CE,则可以使用 MERGE 语句仅遍历表一次 (http://blog.sqlauthority.com/2008/08/28/sql-server-2008-introduction -to-merge-statement-one-statement-for-insert-update-delete/)。您可能还想为 TypeCode、AreaCode 和 Rate 上的度量创建索引,以加快处理速度。

    【讨论】:

    • 哇,谢谢,索引带来了巨大的变化!从40分钟到2分钟左右!
    【解决方案2】:

    这是我将在 SQL 端处理的事情,而不是使用 C#。将所有数据导入到临时表中,使用您提供的字段(TypeCode、Area、Rate、StartDate、EndDate、Description),然后查询出这样的摘要:

    INSERT INTO PermanentTable (TypeCode, Area, Rate, StartDate, EndDate, Description)
    SELECT
        TypeCode, Area, Rate, MIN(StartDate), MAX(EndDate), MIN(Description)
    FROM
        TempLoad
    GROUP BY
        TypeCode, Area, Rate
    

    正如 PoppaVein 指出的那样,如果您有要更新的现有数据,您将需要一个 MERGE。哦,除了索引之外,听起来 { TypeCode, AreaCode, Rate } 应该是永久表的主键。这样做可能会加快速度,并确保您不会导入任何重复的数据。

    我不相信您指定了 Description 的更改是否需要在您的永久表中创建一个新行;我猜它不会。

    我刚刚给出的查询有一个很大的限制:如果您有不连续的时间段适用费率,这将“掩盖”差距。如果有可能,我可以帮助您处理所需的更复杂的查询。实际上,该主题(合并非连续日期范围)经常出现在 SO 上,您可能很容易找到合适的解决方案。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-02-22
      • 1970-01-01
      • 2021-05-04
      • 2022-01-12
      • 2016-11-29
      • 1970-01-01
      • 2019-05-23
      相关资源
      最近更新 更多