【发布时间】:2020-04-24 00:45:32
【问题描述】:
下面是一个虚拟示例,用于演示查询结果有何不同,实际查询更为复杂,因此在此示例中查询结构可能显得过于矫枉过正。建立与 sqlite3 数据库的连接并添加这些记录以开始:
import sqlite3
connection = sqlite3.connect(
'file:test_database',
detect_types=sqlite3.PARSE_DECLTYPES,
isolation_level=None,
check_same_thread=False,
uri=True
)
cursor = connection.cursor()
tableA_records = [(1, 202003), (2, 202003), (3, 202003), (4, 202004), (5, 202004), (6, 202004), (7, 202004), (8, 202004), ]
tableB_records = [(1, 202004), (2, 202004), (3, 202004), (4, 202004), (5, 202004),]
tableA_ddl = """
create table tableA
(
ID int,
RunYearMonth int
);
"""
tableB_ddl = """
create table tableB
(
ID int,
RunYearMonth int
);
"""
cursor.execute(tableA_ddl)
cursor.execute(tableB_ddl)
cursor.executemany("INSERT INTO tableA VALUES (?, ?)", tableA_records)
cursor.executemany("INSERT INTO tableB VALUES (?, ?)", tableB_records)
现在我们有两个表(A 和 B),分别有 8 条和 5 条记录。当日期为202004时,我想计算两者之间具有相同ID和日期的记录。
我现在有这个问题:
SELECT COUNT(*)
FROM (
SELECT *
FROM `tableA`
WHERE `RunYearMonth` = 202004
) AS `A`
INNER JOIN (
SELECT *
FROM `tableB`
WHERE `RunYearMonth` = 202004
) AS `B`
ON `A`.`ID` = `B`.`ID`
AND `A`.`RunYearMonth` = `B`.`RunYearMonth`
正如预期的那样,在 sqlite 控制台中运行时返回 2。
但是,在 Python 中运行时,您会得到不同的结果。
q = """
SELECT COUNT(*)
FROM (
SELECT *
FROM `tableA`
WHERE `RunYearMonth` = 202004
) AS `map1`
INNER JOIN (
SELECT *
FROM `tableB`
WHERE `RunYearMonth` = 202004
) AS `map2`
ON `map1`.`ID` = `map2`.`ID`
AND `map1`.`RunYearMonth` = `map2`.`RunYearMonth`
"""
cursor.execute(q)
print(cursor.fetchall())
这将返回 5,它实际上忽略了子查询中的 WHERE 子句和它们具有相同 RunYearMonth 的连接条件,两者都有记录 1-5。
什么会导致这种差异? Python不是简单的把查询字符串传过去吗?
相关版本:
sqlite3.version == 2.6.0
sqlite3.sqlite_version == 3.31.1
sys.version == 3.6.5
【问题讨论】:
-
我得到 2 用于在 Python 中运行的查询。我的 SQLite 版本是 3.22.0,我的 Python 版本是 3.8.0
-
@mechanical_meat 3.31引入了相关bug。
标签: sql python-3.x sqlite