使用 != (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 语句未返回正确的值的主要内容,如果未能解决你的问题,请参考以下文章