首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >WHERE子句对虚假结果的解释

WHERE子句对虚假结果的解释
EN

Stack Overflow用户
提问于 2019-01-08 11:58:08
回答 2查看 76关注 0票数 3

MySQL 8.由于缺少表名规范,我在查询中看到一个伪行返回。我知道怎么解决它,我想知道为什么会发生这种情况。

请看下面的小提琴:

http://sqlfiddle.com/#!9/beb1ed/1/0

其目的是查找计划表中也存在的任何行,这些行由SubscriptionID和date匹配。

返回的结果如下:

代码语言:javascript
代码运行次数:0
运行
复制
RealWorldVisitDate      CustomerID      SubscriptionID
2019-01-14 00:00:00     5               13  
2019-01-14 00:00:00     17              23  

然而,WHERE子句应该将结果限制在第一行(CustomerID 5/ SubscriptionID 13)。

--我知道解决方案修复这个问题并返回正确的行--在WHERE中指定表,如下所示:

代码语言:javascript
代码运行次数:0
运行
复制
SELECT * FROM tblPlanned WHERE ( SELECT COUNT(1) FROM tblScheduled WHERE tblScheduled.SubscriptionID = **tblPlanned.**SubscriptionID AND tblScheduled.DateScheduled = RealWorldVisitDate ) > 0

但是,我想了解为什么原始查询(按按小提琴计算)返回CustomerID 17 / SubscriptionID 23的虚假行,将其看作是与date和SubscriptionID在tblScheduled中不存在的组合的一行。这显然与两个表中重复的SubscriptionID列名有关,但我无法理解导致它的mysql执行逻辑。

(由于以前对细节过多的抱怨,问题被故意缩短了。问我你是否需要进一步的数据等)。

谢谢。

模式和数据按小提琴:

代码语言:javascript
代码运行次数:0
运行
复制
CREATE TABLE `tblScheduled` (
  `ScheduledTargetID` bigint(20) NOT NULL,
  `DateScheduled` datetime NOT NULL,
  `CustomerID` int(10) UNSIGNED NOT NULL,
  `SubscriptionID` int(10) UNSIGNED NOT NULL
);

INSERT INTO `tblScheduled` (`ScheduledTargetID`, `DateScheduled`, `CustomerID`, `SubscriptionID`) VALUES
(25, '2018-11-19 00:00:00', 16, 15),
(24, '2018-11-19 00:00:00', 17, 23),
(27, '2018-11-23 00:00:00', 5, 1),
(26, '2018-11-23 00:00:00', 14, 18),
(23, '2019-01-14 00:00:00', 5, 13);

CREATE TABLE `tblPlanned` (
  `RealWorldVisitDate` datetime DEFAULT NULL,
  `CustomerID` int(10) UNSIGNED DEFAULT NULL,
  `SubscriptionID` int(10) UNSIGNED DEFAULT NULL
);

INSERT INTO `tblPlanned` (`RealWorldVisitDate`, `CustomerID`, `SubscriptionID`) VALUES
('2019-01-15 00:00:00', 5, 4),
('2019-01-14 00:00:00', 5, 13),
('2019-01-28 00:00:00', 5, 27),
('2019-01-14 00:00:00', 17, 23),
('2019-02-11 00:00:00', 17, 23);


SELECT * FROM tblPlanned WHERE ( SELECT COUNT(1) FROM tblScheduled WHERE tblScheduled.SubscriptionID = SubscriptionID AND tblScheduled.DateScheduled = RealWorldVisitDate ) > 0
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-01-08 12:10:28

MySQL将在子查询中查找列的默认位置是您要从中查询的表。

代码语言:javascript
代码运行次数:0
运行
复制
SELECT COUNT(1) 
FROM tblScheduled
WHERE tblScheduled.SubscriptionID = SubscriptionID AND tblScheduled.DateScheduled = RealWorldVisitDate

实际上与以下内容相同:

代码语言:javascript
代码运行次数:0
运行
复制
SELECT COUNT(1) 
FROM tblScheduled
WHERE tblScheduled.SubscriptionID = tblScheduled.SubscriptionID AND tblScheduled.DateScheduled = RealWorldVisitDate

这相当于

代码语言:javascript
代码运行次数:0
运行
复制
SELECT COUNT(1) 
FROM tblScheduled 
WHERE tblScheduled.DateScheduled = RealWorldVisitDate

这解释了您所得到的结果,因为tblScheduled中的行与DateScheduled='2019-01-14 00:00:00'匹配了tblPlanned中的两行( [CustomerID, SubscriptionID] = [5,13][17,23])。

票数 4
EN

Stack Overflow用户

发布于 2019-01-08 12:11:10

“查找计划表中也存在的任何行”

这正是内连接的作用所在:

代码语言:javascript
代码运行次数:0
运行
复制
SELECT * 
FROM tblPlanned 
INNER JOIN tblScheduled 
  ON tblScheduled.SubscriptionID = tblPlanned.SubscriptionID 
  AND tblScheduled.DateScheduled = tblPlanned.RealWorldVisitDate;

这是一种更清晰、更有效的匹配行的方法,在这种场景中,这是SQL中的标准操作。

您最初的尝试是有缺陷的,部分原因是没有使用这种方法,但也是因为在子查询中使用哪个SubscriptionID字段的模糊性--默认情况下,它与子查询中的表匹配,因此您只是获得字段与其自身匹配的结果。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/54091360

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档