[英]Python sqlite3: Diff of table in two databases
我有兩個具有相同模式的數據庫,我想在其中一個表上有效地進行差異。 即僅返回唯一記錄,折扣主鍵。
columns = zip(*db1.execute("PRAGMA table_info(foo)").fetchall())[1]
db1.execute("ATTACH DATABASE '/path/to/db1.db' AS db1")
db1.execute("ATTACH DATABASE '/path/to/db2.db' AS db2")
db2.execute("ATTACH DATABASE '/path/to/db1.db' AS db1")
db2.execute("ATTACH DATABASE '/path/to/db2.db' AS db2")
data = db2.execute("""
SELECT
one.*
FROM
db1.foo AS one
JOIN db2.foo
AS two
WHERE {}
""".format(' AND '.join( ['one.{0}!=two.{0}'.format(c) for c in columns[1:]]))
).fetchall()
也就是說,忽略主鍵(在這種情況下是meow
),不要返回兩個數據庫中存在相同的記錄。
db1
的表foo
如下所示:
meow mix please deliver
1 123 abc
2 234 bcd two
3 345 cde
db2
的表foo
看起來像:
meow mix please deliver
1 345 cde
2 123 abc one
3 234 bcd two
4 456 def four
所以db2
的唯一條目是:
[(2, 123, 'abc', 'one'), (4, 456, 'def', 'four')]
這就是我得到的。 如果我有兩列以上,這很有效。 但是如果只有兩個,即主鍵和一個值,例如在查找表中:
bar baz bar baz
1 123 1 234
2 234 2 345
3 345 3 123
4 456
我得到所有非唯一值重復N-1次,唯一值重復N次,其中N是db1
的記錄數。 我理解為什么會這樣,但我不知道如何解決它。
[(1, '234'),
(1, '234'),
(2, '345'),
(2, '345'),
(3, '123'),
(3, '123'),
(4, '456'),
(4, '456'),
(4, '456')]
我有一個想法是在拉出所有重復結果后取出模數:
N = db1.execute("SELECT Count(*) FROM foo").fetchone()[0]
data = [
list(data)
for data,n in itertools.groupby(sorted(data))
if np.mod(len(list(n)),N)==0
]
哪個工作:
[[4, '456']]
但這看起來很混亂,如果可能的話,我想在第一個SQL查詢中完成所有操作。
此外,在大型表(我的真實數據庫有~10k記錄)上,這需要很長時間。 有什么辦法優化這個? 謝謝!
取代我之前的答案 - 這是一個很好的通用解決方案。
輸入表看起來像這樣:
sqlite> select * from t1;
meow mix please delivery
---------- ---------- ---------- ----------
1 123 abc
2 234 bcd two
3 345 cde
和
sqlite> select * from t2;
meow mix please delivery
---------- ---------- ---------- ----------
1 345 cde
2 123 abc one
3 234 bcd two
4 456 def four
你可以得到t2 /不在t1(忽略PK)的記錄,如下所示:
select sum(q1.db), mix, please, delivery from (select 1 as db, mix, please,
delivery from t1 union all select 2 as db, mix, please, delivery from t2) q1
group by mix, please, delivery having sum(db)=2;
sum(q1.db) mix please delivery
---------- ---------- ---------- ----------
2 123 abc one
2 456 def four
您可以通過更改having子句中的值來執行不同的set操作。 SUM(DB)=1
返回1 /不是2的記錄; SUM(DB)=2
返回2 /不是1的記錄; SUM(DB)=1 OR SUM(DB)=2
返回存在於其中的記錄,但不返回兩者; 和SUM(DB)=3
返回兩者中存在的記錄。
唯一不適合你的是返回PK。 這在我編寫的查詢中無法完成,因為GROUP BY
和SUM
操作僅適用於公共/聚合數據,PK字段根據定義是唯一的。 如果您知道每個數據庫中非PK字段的組合是唯一的,您可以使用返回的記錄創建新查詢以查找PK。
請注意,此方法很好地擴展到超過2個表。 通過使db字段的冪為2,您可以對任意數量的表進行操作。 例如,如果您為t1執行了1作為數據,對於t2執行了2作為db,對於t3執行了4作為db,對於t4執行了db作為db,則可以通過更改條件來找到所需表的任何相交/差異 - 例如, HAVING SUM(DB)=5
將返回t1和t3中的記錄,但不返回t2或t4中的記錄。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.