where子句错误结果的解释

7kjnsjlb  于 2021-06-15  发布在  Mysql
关注(0)|答案(2)|浏览(301)

mysql 8。我看到查询中返回了一个虚假的行,这是由于缺少表名的规范。我知道怎么修,我想知道为什么会这样。
请看以下小提琴:
http://sqlfiddle.com/#!9月1日
目的是在计划表中查找与subscriptionid和date匹配的、计划表中也存在的任何行。
返回的结果是:

RealWorldVisitDate      CustomerID      SubscriptionID
2019-01-14 00:00:00     5               13  
2019-01-14 00:00:00     17              23

但是where子句应该将结果限制在第一行(customerid5/subscriptionid13)。
我知道解决此问题并返回正确行的方法是根据以下查询在where中指定表:

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

但是我想理解为什么原始查询(根据fiddle)返回customerid17/subscriptionid23的一个伪行,因为在tblscheduled中不存在带有这个日期和subscriptionid组合的行。这显然与两个表中重复的subscriptionid列名有关,但我无法理解导致它的mysql执行逻辑。
(由于之前抱怨过多细节,问题故意简短。询问我是否需要进一步的数据等)。
谢谢您。
架构和数据按小提琴:

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
roejwanj

roejwanj1#

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

SELECT COUNT(1) 
FROM tblScheduled
WHERE tblScheduled.SubscriptionID = SubscriptionID AND tblScheduled.DateScheduled = RealWorldVisitDate

实际上与:

SELECT COUNT(1) 
FROM tblScheduled
WHERE tblScheduled.SubscriptionID = tblScheduled.SubscriptionID AND tblScheduled.DateScheduled = RealWorldVisitDate

相当于

SELECT COUNT(1) 
FROM tblScheduled 
WHERE tblScheduled.DateScheduled = RealWorldVisitDate

这就解释了你在这一行之后得到的结果 tblScheduledDateScheduled='2019-01-14 00:00:00' 匹配中的两行 tblPlanned (那些 [CustomerID, SubscriptionID] = [5,13] 以及 [17,23] ).

yrdbyhpb

yrdbyhpb2#

“查找计划表中同时存在于计划表中的任何行”
这正是内部联接的作用:

SELECT * 
FROM tblPlanned 
INNER JOIN tblScheduled 
  ON tblScheduled.SubscriptionID = tblPlanned.SubscriptionID 
  AND tblScheduled.DateScheduled = tblPlanned.RealWorldVisitDate;

这是一种更清晰、更有效的匹配行的方法,在这种情况下,这是sql中的标准操作。
您最初的尝试有缺陷,部分原因是没有使用这种方法,但也因为子查询中要使用哪个subscriptionid字段的模糊性——默认情况下,它与子查询中的表匹配,所以您只得到字段自身匹配的结果。

相关问题