2012-02-14 51 views
0

我正在進行從程序A的CSV格式到程序B的CSV格式的數據格式轉換。加強/檢查多個表中主鍵的唯一性

計劃A的格式如下:

Fruit, Orange, $1.99 
Fruit, Apple, $2.99 
Fruit, Pear, $5.99 
Colour, Red, #FF0000 
Colour, Green, #00FF00 
Colour, Blue, #0000FF 
Colour, Orange, #FF8800 

我已經轉換計劃A的CSV文件導入包含多個表,一個是在原來的CSV文件中每種類型的記錄的SQLite數據庫。這裏是FruitColour。這很好映射到程序B的文件格式,該文件格式使用類似的表格(需要幾個時髦的轉換)。

程序A的CSV文件中的每個表都有一個不需要唯一的ID主鍵。也就是說,可以存在ID爲「Orange」的「Fruit」行和ID爲「Orange」的「Colour」行。

但是,程序B會認爲這是一個錯誤 - 它要求ID主鍵在所有表中都是唯一的。

在原始文件(格式如上)或SQL數據庫中,檢測非唯一ID密鑰的有效方法是什麼?有幾十個表格和數千個記錄。

我目前的做法是類似(Python代碼):

import sqlite3, collections 
db_conn = sqlite3.connect('db.sqlite3') 
db_conn.row_factory = sqlite3.Row 

IDs = [] # build a list of (ID, table_name) pairs 

tables = ['Fruit','Colour']; 
for table in tables: 
    rows = db_conn.execute("SELECT ID FROM %s" % table) 
    for row in rows: 
     IDs.append((row['ID'],table)) 

id_counts = collections.Counter([x(0) for x in IDs]) 
duplicated_ids = [x for x in id_counts if id_counts[x] > 1] 
for duplicated_id in duplicated_ids:  
    duplicated_types = [x(1) for x in IDs if x(0) == duplicated_id ] 
    print ("Duplicate ID %(duplicated_id)s used for %(duplicated_types)s" % locals()) 

這似乎歡快效率低下。必須有一個更優雅/更Pythonic的方式來做到這一點,可能使用某種設置符號。

或者,我可以定義我的SQL模式(SQLite風格),以便SQLite強制所有表的ID的唯一性?

回答

1

沒有辦法,我知道在數據庫中執行此操作,除非你創建的所有ID另一個表,這樣保持下去,以日期使用觸發器。我不確定你是否想要做這樣的事情(不管它有可能取決於你的數據庫引擎)。

的更有效的方法來檢查重複被以陣列的代替利用哈希:

IDs = {} 

tables = ['Fruit','Colour']; 
for table in tables: 
    rows = db_conn.execute("SELECT ID FROM %s" % table) 
    for row in rows: 
    if IDs.has_key(row['ID']): 
     print "Duplicate ID %s is present in both %s and %s" % (row['ID'], table, IDs[row['ID']]) 
    else: 
     IDs[row['ID']] = table 

它不給相當TE相同的輸出(特別是當一個關鍵是存在於3代表它贏得沒有顯示所有的排列),但它會很快告訴你你的問題在哪裏。

+0

這是搖滾樂對StackOverflow的第一個貢獻 - 歡迎! :)我喜歡這個解決方案只需要一次通過數據(如果有很多重複項,我的是'O(n^2)'。) – 2012-02-14 09:26:11

+0

在進一步的思考中,這可以很容易地擴展到報告一式三份,一式四份等等,通過允許多個表名稱在散列中累積。即如果散列鍵已經存在,則將'IDs [row ['ID']] + = table'插入散列表。需要一點點生產好的輸出,但保持良好的性能特點。 – 2012-02-14 09:34:35

+0

謝謝:)。請注意,哈希函數是O(1),所以這個解決方案的確是O(n) 事實上,當ID出現在兩個以上的表中時,應該很容易得到正確的輸出:只需將ID [row ['ID ']]數組並添加表格(不打印任何內容)。然後循環通過ID散列並打印數組長度超過1的任何條目。 – Claude 2012-02-14 10:03:27