我编写的一段sql没有按预期的方式运行。一个重要的逻辑是计算有多少客人是VIP,但是sql似乎总是得到一个错误的答案。
以下数据库有6位访客,其中3位是VIP。
CREATE TABLE `guest` (
`GuestID` int(11) NOT NULL DEFAULT '0',
`fullname` varchar(255) DEFAULT NULL,
`vip` tinyint(1) DEFAULT '0',
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
--
-- Dumping data for table `guest`
--
INSERT INTO `guest` (`GuestID`, `fullname`, `vip`) VALUES
(912, 'Sam', 0),
(321, 'Sev', 0),
(629, 'Joe', 0),
(103, 'Tom', 1),
(331, 'Cao', 1),
(526, 'Conor', 1);
最初,sql返回一个值,表示有5个vip,这是不正确的,因为只有3个vip。这是一个相当复杂的数据库,在为这个问题生成一个最小可行的示例时(有一个可重复的错误),脚本现在声明只有2个vip。同样,这是不正确的。
所讨论的sql是
SELECT slotguest.FK_SlotNo, Count(CASE WHEN guest.vip = 1 THEN 1 END) AS guest_count
FROM guest
INNER JOIN slotguest ON guest.GuestID = slotguest.FK_guest
GROUP BY slotguest.FK_SlotNo;
最慢的结构和内容如下
CREATE TABLE `slotguest` (
`FK_SlotNo` int(11) NOT NULL,
`FK_guest` int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
--
-- Dumping data for table `slotguest`
--
INSERT INTO `slotguest` (`FK_SlotNo`, `FK_guest`) VALUES
(396, 912),
(396, 321),
(396, 629),
(396, 103),
(396, 331),
(396, 526);
是什么导致count得出一个一贯错误的答案?
3条答案
按热度按时间8wigbo561#
如注解中所示(从users@f处检查ábio amorim,@rajat),您的查询似乎按预期运行。因为,你用
CASE WHEN
,使用SUM
.如果您将不同vip类别的计数带到可能存在数据泄漏的位置,可能会更加明显。
643ylb082#
闻起来像“爆炸-内爆”。鉴于
查询是这样执行的:
JOIN
table。假设表的比例不是1:1,这将导致比任何一个表都多的行。不使用骨料(例如
COUNT
)靠着那张临时table。只有到那时
GROUP BY
收缩回最初所需的行数。解决方案是避免对包含被计数/求和数据的多个表进行聚合。有时这种模式是
drnojrws3#
为了解释问题所在,并给出一个更接近o.p.询问的答案。。。
(我假设o.p.是出错的一个简化示例,而实际的查询更为复杂。如果我们知道大局,我想我不会那样编码。)
在o.p.查询中,
CASE WHEN guest.vip = 1 THEN 1 END
格式不正确。这是一个条件表达式;它应该为查询检索到的所有行返回一个特定值,即guest.vip <> 1
.事实上,行为是没有定义的;它在一些数据库管理系统上产生预期的答案,正如注解所说明的那样;按照o.p.的说法,它不会影响其他人。我猜对于那些产生预期答案的人来说,dbms是在处理
CASE
作为回报Null
,然后Count( )
正在忽略空值。这是一个更可怕的后果Null
在sql中。所以根据@fábio amorim的评论
CASE
需要一个ELSE
因此Count( )
给出了一个无用的结果,所以得到ELSE
返回0
以及Sum( )
这个1
或者0
: