2009-06-19 57 views
0

我已經得到了提供對象及其屬性的列表數據源更新列表(CSV文件,但是這並不重要)。每次運行程序時,都需要拉取對象列表的新副本,將其與存儲在數據庫中的對象(及其屬性)列表進行比較,並根據需要更新數據庫。算法從列表

與新對象打交道是很容易 - 數據源給每一個對象順序的ID號,檢查對數據庫的新信息上的ID號,就大功告成了。我正在尋找其他案例的建議 - 當某個對象的某些屬性發生變化時,或者某個對象已被刪除時。

一個幼稚的解決方案是從數據庫中提取所有對象,並獲得兩組(新舊)交集的補充,然後檢查這些結果,但似乎效率不高如果集合變大。有任何想法嗎?

+2

計算並存儲每個對象的哈希值? – FogleBird 2009-06-19 18:12:19

回答

1

大量數據的標準方法相當於此。

我們假設LIST_1是「主」(不重複)和list_2是「更新」可能有重複。

iter_1 = iter(sorted(list_1)) # Essentially SELECT...ORDER BY 
iter_2 = iter(sorted(list_2)) 
eof_1 = False 
eof_2 = False 
try: 
    item_1 = iter_1.next() 
except StopIteration: 
    eof_1= True 
try: 
    item_2 = iter_2.next() 
except StopIteration: 
    eof_2= True 
while not eof_1 and not eof_2: 
    if item_1 == item_2: 
     # do your update to create the new master list. 
     try: 
      item_2 = iter_2.next() 
     except StopIteration: 
      eof_2= True 
    elif item_1 < item_2: 
     try: 
      item_1 = iter_1.next() 
     except StopIteration: 
      eof_1= True 
    elif item_2 < item_1: 
     # Do your insert to create the new master list. 
     try: 
      item_2 = iter_2.next() 
     except StopIteration: 
      eof_2= True 
assert eof_1 or eof_2 
if eof_1: 
    # item_2 and the rest of list_2 are inserts. 
elif eof_2: 
    pass 
else: 
    raise Error("What!?!?") 

是的,它涉及潛在的排序。如果list_1在寫回文件系統時按照排序順序保存,則可節省大量時間。如果list_2可以在保持排序的結構中累積,那麼可以節省相當多的時間。

對不起,你需要知道哪個迭代器產生了StopIteration,所以你不能(平凡地)將整個while循環包裝在一個大的嘗試塊中。

1

有沒有辦法來維持現場「修改的最後一次」?這聽起來就像是你真正想要的:與上一次更改/刪除(/添加)對象相比,基於上次備份運行的增量備份。

+0

或修改字段也會很棒! – 2009-06-19 18:26:46

0

當你拉清單到你的程序,遍歷列表做基於該映射到該對象的距離一樣的ObjectName列表相同的屬性數據庫表列屬性的查詢。或者你可以將整個表加載到一個列表中,並以這種方式比較列表。我假設你有除了數據庫分配的ID之外存在的唯一對象。

如果沒有在表中通過查詢發現,對象,創建一個新條目。如果發現像FogleBird提到的那樣,請在表中爲該對象存儲計算出的散列或CRC,以便與列表中的對象進行比較(對該對象運行計算)。如果散列不匹配,則使用列表中的那個更新該對象。

1

您需要在數據庫和CSV文件中都有時間戳。時間戳應顯示記錄更新時的數據,並且應該將記錄的時間戳與相同的ID進行比較以決定是否需要更新它

至於您對交集的想法... 它應該完成反之亦然! 您必須將CSV中的所有數據導入臨時表,並在2個SQL數據庫表之間進行交集。如果您使用Oracle或MS SQL 2008(2005年不確定),您會發現一個非常有用的MERGE關鍵字,因此您可以用較少的努力編寫SQL,然後再花費其他編程語言來合併數據。