我参加聚会有点晚了,但我偶然发现了这个寻找类似问题的信息。我想我可能会分享我的解决方案,以防它可以帮助其他人或 OP,如果他/她仍在研究它。这是我的问题和我所做的:
我有一个已建立的 Access 数据库,其行数与 OP 大致相同(6 列,约 850k 行)。我们大约每周一次从合作伙伴公司收到一个带有一张表的 .xlsx 文件和与数据库相同结构的数据。
这个文件包含整个数据库,加上更新(新记录和对旧记录的更改,没有删除)。第一列包含每一行的唯一标识符。当我们通过 Parfait 建议的类似查询收到文件时,Access db 会更新,但由于它是整个 850k+ 记录,因此需要 10-15 分钟或更长时间来比较和更新,具体取决于我们正在进行的其他操作。
由于仅将更改加载到当前 Access db 中会更快,因此我需要生成一个 delta 文件(最好是 .txt,可以使用 excel 打开并在需要时另存为 .xlsx)。我认为这类似于 OP 正在寻找的东西。为此,我用 C++ 编写了一个小应用程序来比较前一周的文件和本周的文件。数据本身是字符和数字数据的混合体,为简单起见,我将在此处将其称为 string1 到 string6。它看起来像这样:
Col1 Col2 Col3 Col4 Col5 Col6
string1 string2 string3 string4 string5 string6
.......
''''Through 850k rows''''
将两个 .xlsx 文件保存为 .txt 制表符分隔文件后,它们如下所示:
Col1\tCol2\tCol3\tCol4\tCol5\tCol6\n
string1\tstring2\tstring3\tstring4\tstring5\tstring6\n
....
//Through 850k rows//
有趣的部分!我将旧的 .txt 文件存储为哈希表(使用标准库中的 c++ unordered_map)。然后使用来自新 .txt 文件的输入文件流,我在新文件中使用 Col1 作为哈希表的键,并将任何差异输出到两个不同的文件。一种是您可以使用查询将新数据附加到数据库中,而另一种则可以用于更新已更改的数据。
我听说可以创建一个比unordered_map 更有效的哈希表,但目前,这很有效,所以我会坚持下去。这是我的代码。
#include <iostream>
#include <fstream>
#include <string>
#include <iterator>
#include <unordered_map>
int main()
{
using namespace std;
//variables
const string myInFile1{"OldFile.txt"};
const string myInFile2{"NewFile.txt"};
string mappedData;
string key;
//hash table objects
unordered_map<string, string> hashMap;
unordered_map<string, string>::iterator cursor;
//input files
ifstream fin1;
ifstream fin2;
fin1.open(myInFile1);
fin2.open(myInFile2);
//output files
ofstream fout1;
ofstream fout2;
fout1.open("For Updated.txt"); //updating old records
fout2.open("For Upload.txt"); //uploading new records
//This loop takes the original input file (i.e.; what is in the database already)
//and hashes the entire file using the Col1 data as a key. On my system this takes
//approximately 2 seconds for 850k+ rows with 6 columns
while(fin1)
{
getline(fin1, key, '\t'); //get the first column
getline(fin1, mappedData, '\n'); //get the other 5 columns
hashMap[key] = mappedData; //store the data in the hash table
}
fin1.close();
//output file headings
fout1 << "COl1\t" << "COl2\t" << "COl3\t" << "COl4\t" << "COl5\t" << "COl6\n";
fout2 << "COl1\t" << "COl2\t" << "COl3\t" << "COl4\t" << "COl5\t" << "COl6\n";
//This loop takes the second input file and reads each line, first up to the
//first tab delimiter and stores it as "key", then up to the new line character
//storing it as "mappedData" and then uses the value of key to search the hash table
//If the key is not found in the hash table, a new record is created in the upload
//output file. If it is found, the mappedData from the file is compared to that of
//the hash table and if different, the updated record is sent to the update output
//file. I realize that while(fin2) is not the optimal syntax for this loop but I
//have included a check to see if the key is empty (eof) after retrieving
//the current line from the input file. YMMV on the time here depending on how many
//records are added or updated (1000 records takes about another 5 seconds on my system)
while(fin2)
{
getline(fin2, key, '\t'); //get key from Col1 in the input file
getline(fin2, mappedData, '\n'); //get the mappeData (Col2-Col6)
if(key.empty()) //exit the file read if key is empty
break;
cursor = hashMap.find(key); //assign the iterator to the hash table at key
if(cursor != hashMap.end()) //check to see if key in hash table
{
if(cursor->second != mappedData) //compare mappedData
{
fout2 << key << "\t" << mappedData<< "\n";
}
}
else //for updating old records
{
fout1 << key << "\t" << mappedData<< "\n";
}
}
fin2.close();
fout1.close();
fout2.close();
return 0;
}
我正在做一些事情来使它成为一个易于使用的可执行文件(例如读取 excel.zip 文件的 xml 结构以便直接读取或使用 ODBC 连接),但现在,我'我只是对其进行测试以确保输出正确。当然,必须使用类似于 Parfait 建议的查询将输出文件加载到访问数据库中。此外,我不确定 Excel 或 Access VBA 是否有用于构建哈希表的库,但如果它可以节省访问 Excel 数据的时间,则可能值得进一步探索。欢迎任何批评或建议。