我有两个具有相同架构的数据库,我想在其中一个表上有效地执行差异。即只返回唯一记录,折扣主键。
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
),不要返回两个数据库中存在相同的记录。
foo
中的表格db1
如下所示:
meow mix please deliver
1 123 abc
2 234 bcd two
3 345 cde
foo
中的表格db2
如下:
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记录)上,这需要很长时间。有什么办法优化这个?谢谢!
答案 0 :(得分:3)
取代我之前的答案 - 这是一个很好的通用解决方案。
输入表格如下:
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作为db,对于t2执行2作为db,对t3执行4作为db,对t4执行db作为db,则可以通过更改条件来找到所需表的任何相交/差异 - 例如HAVING SUM(DB)=5
将返回t1和t3中的记录,但不返回t2或t4中的记录。