sqlite3在控制台与Python脚本的结果不同

问题描述 投票:0回答:1

下面是一个虚例来演示查询结果的不同,真实的查询比较复杂,所以在这个例子中,查询结构可能会显得矫枉过正。建立一个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条记录。我想统计两者之间ID和日期相同的记录,当日期为 202004.

我现在有这个查询。

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`

这和预期一样,返回 2 当在 sqlite 控制台中运行时。

但在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
sql python-3.x sqlite
1个回答
1
投票

我使用你的第一个脚本创建了一个测试数据库,然后在sqlite3 shell中打开它。你的查询在里面返回5条,而不是你得到的2条。改为显示所有的行,而不仅仅是计数后,结果是。

ID          RunYearMonth  ID          RunYearMonth
----------  ------------  ----------  ------------
1           202003        1           202004
2           202003        2           202004
3           202003        3           202004
4           202004        4           202004
5           202004        5           202004

我不知道为什么表A中RunYearMonth为2023003的记录会被包含在内 我想它们应该被子查询的过滤掉了 WHERE.

这似乎是Sqlite3中的一个错误--使用旧版本(3.11.0)会得到预期的结果,稍微调整一下查询以去除 AND map1.RunYearMonth = map2.RunYearMonth 在3.31.1上产生正确的结果。


无论如何,这个查询可以被显著地清理,像这样。

SELECT count(*)
FROM tableA AS A
JOIN tableB AS B ON A.ID = B.ID
                AND A.RunYearMonth = B.RunYearMonth
WHERE A.RunYearMonth = 202004;

它确实返回了预期的2个数。

© www.soinside.com 2019 - 2024. All rights reserved.