Составные записи с разными датами с использованием SQL - PullRequest
2 голосов
/ 09 февраля 2011

Я должен прочитать исторические данные таможенных тарифов из большого текстового файла в базу данных, но данные немного запутались.

Тариф состоит из типа и меры (фактические ставки и даты вступления в силу)

A type определяется тип-кодом и описанием. Меры содержат курсы, географический регион, к которому они применяются, курс, а также дату начала и дату окончания.

Проблема в том, что для одного и того же тарифа существует несколько записей с разными датами вступления в силу, которые необходимо объединить в одну запись.

Текстовый файл выглядит примерно так:

(TypeCode, Area, Rate, StartDate, EndDate, Description)
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 нужно объединить в один измерить с первой даты начала и последняя конечная дата (01029000 # GEN # 00000040.000% # 20050101 # 20071231 # ДРУГОЙ #)
  • 6 должен оставаться отдельным, потому что он имеет другой курс
  • 7 должен оставаться отдельным, потому что это из другого географического района

Я использую c # и Sql Compact Edition. У меня он в основном работает, но он ОЧЕНЬ медленный ... Должен быть более эффективный способ сделать это в тот момент, когда на моем ноутбуке Intel i3 требуется около 40 минут (66000 записей)

Я записал свои шаги и дал код для составной части. Мне нужно проверить, являются ли даты и последующими.

Шаги:
Читайте текстовый файл построчно
Разбить линию на токены
Вставьте уникальные коды типов и их описания в таблицу 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();
}

Любая помощь или предложения будут оценены!

Ответы [ 2 ]

0 голосов
/ 26 марта 2011

Это то, что я бы обработал на стороне 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, вы, вероятно, можете найти подходящее решение довольно легко.

0 голосов
/ 09 февраля 2011

Если вы используете 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/).. Возможно, вы захотите создать индекс для Measures для TypeCode, AreaCode и Rate, чтобы ускорить процесс. а также.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...