使用 != (sqlite3) 时 SELECT 语句未返回正确的值

Posted

技术标签:

【中文标题】使用 != (sqlite3) 时 SELECT 语句未返回正确的值【英文标题】:SELECT statement not returning correct values when using != (sqlite3) 【发布时间】:2015-04-08 13:41:24 【问题描述】:

我有两张表,SALES_REP 和 UNAVAILABLE DATES:

import sqlite3
booking = sqlite3.connect('AppointmentBookingSystem.db')

booking.execute('''CREATE TABLE SALES_REP
        (repID INTEGER PRIMARY KEY AUTOINCREMENT,
        username TEXT NOT NULL COLLATE NOCASE,
        numberOfAppointments INT DEFAULT 0,
        FOREIGN KEY (username) REFERENCES USERNAME_PASSWORD(username));''')

booking.execute('''CREATE TABLE UNAVAILABLE_DATES
        (dateID INTEGER PRIMARY KEY AUTOINCREMENT,
        date DATE NOT NULL);''')

这两个表之间的关系是多对多的,所以我创建了一个带有复合主键的链接表:

booking.execute('''CREATE TABLE DATES_REPS
        (dateID INTEGER NOT NULL,
        repID INTEGER NOT NULL,
        PRIMARY KEY(dateID, repID),
        FOREIGN KEY (dateID) REFERENCES UNAVAILABLE_DATES(dateID),
        FOREIGN KEY (repID) REFERENCES SALES_REP(repID));''')

我正在尝试使用 SQL 选择语句从 SALES_REP 中获取在 UNAVAILABLE_DATES 表中的日期不存在的所有 repID 的列表

date = 2015-09-25
c = booking.cursor()
cursor = c.execute('SELECT SALES_REP.repID FROM SALES_REP, DATES_REPS, UNAVAILABLE_DATES\
    WHERE UNAVAILABLE_DATES.date=? AND UNAVAILABLE_DATES.dateID = DATES_REPS.dateID AND SALES_REP.repID != DATES_REPS.repID', (date,))
IDs = c.fetchall()

当我在 DATES_REPS 表中只有 1 条记录时,这将按预期工作

SALES_REP TABLE
repID
------
  1
  2
  3

UNAVAILABLE_DATES TABLE
dateID  |  date
---------------
   1     2015-09-25

DATES_REPS
dateID  |  repID
-------------------
  1          1

返回:

IDs = [(2,), (3,)]

但是,在向 DATES_REPS 和 UNAVAILABLE_DATES 表添加另一条记录后,选择语句不再正常工作

SALES_REP TABLE
repID
------
  1
  2
  3

UNAVAILABLE_DATES TABLE
dateID  |  date
---------------
   1     2015-09-25
   2     2015-09-25

DATES_REPS
dateID  |  repID
-------------------
  1          1
  2          2

我现在期望得到的是“3”,但我得到了

IDs = [(1,), (2,), (3,), (3,)]

随着我向 UNAVAILABLE_DATES 和 DATES_REPS 添加更多记录,这种模式仍在继续

我假设正在发生的是 SALES_REP.repID != DATES_REPS.repID 正在为 DATES_REPS 表中的每条记录返回(因此,当存在 1 时,返回 2 和 3,当存在 2 时,返回 1 和 3等),而不是在该日期的整个表中不存在的 repID

这与我的表连接方式有关吗?还是我的 select 语句有问题?

【问题讨论】:

试试这个<> 而不是!= 返回相同的结果 【参考方案1】:

您已经正确推断出 SQL 如何评估查询。

如果要检查某些行是否不存在,则应使用 NOT EXISTS(带有correlated subquery):

SELECT repID
FROM SALES_REP
WHERE NOT EXISTS (SELECT 1
                  FROM DATES_REPS
                  JOIN UNAVAILABLE_DATES USING (dateID)
                  WHERE UNAVAILABLE_DATES.date = ?
                    AND SALES_REP.repID = DATES_REPS.repID)

【讨论】:

SALES_REP.repID != DATES_REPS.repID!= 不应该是= 吗? 刚刚尝试过,并将 != 更改为 =,正如 @Andomar 所说,这是有效的,谢谢!【参考方案2】:

date 创建多对多关系是不寻常的。只需两张表,您的设计可能会更简单:

SalesPerson: ID, Name, ...
SalesPersonUnavailable: SalesPersonID, Date

(SalesPersonID, Date) 上使用主键以保持一致性。

现在你可以像这样查询:

select  name
from    SalesPerson sp
where   not exists
        (
        select  *
        from    SalesPersonUnavailable spu
        where   spu.Date = ?
                and sp.ID = spu.SalesPersonID
        )

【讨论】:

以上是关于使用 != (sqlite3) 时 SELECT 语句未返回正确的值的主要内容,如果未能解决你的问题,请参考以下文章

字符串比较时如何将Sqlite3设置为不区分大小写?

IOS 开发学习33 使用sqlite3

Sqlite3数据库Python基础操作

SQLite3-我怎样才能加快这个 SELECT 查询?

《SQLite3 — 子句》

《SQLite3 — 运算符》