SELECT 查询不返回没有 ORDER BY 子句的结果
Posted
技术标签:
【中文标题】SELECT 查询不返回没有 ORDER BY 子句的结果【英文标题】:SELECT query returns no result without ORDER BY clause 【发布时间】:2014-05-20 17:19:43 【问题描述】:我有这个问题:
SELECT `Stocks`.`id` AS `Stocks.id` , `Locations`.`id` AS `Locations.id`
FROM `rowiusnew`.`c_stocks` AS `Stocks`
LEFT JOIN `rowiusnew`.`g_locations` AS `Locations` ON ( `Locations`.`ref_id` = `Stocks`.`id` AND `Locations`.`ref_type` = 'stock' )
GROUP BY `Stocks`.`id`
HAVING `Locations.id` IS NOT NULL
这会返回 0 个结果。
当我添加时
ORDER BY Locations.id
对于完全相同的查询,我正确地得到 3 个结果。 值得注意的是:当我丢弃 GROUP BY 子句时,我得到相同的 3 个结果。分组对于带有附加连接的完整查询是必要的;这是演示问题的简化版。
我的问题是:为什么我没有得到原始查询的结果?
请注意,JOIN ON 子句中有两个条件。更改或删除大括号或更改这些条件的顺序不会改变结果。
通常,您会怀疑g_locations
中的字段id
有时为NULL,因此ORDER BY 子句使正确引用的结果显示在组数据集的“顶部”。不是这种情况; id
字段已正确设置为主键字段并使用 auto_increment。
EXPLAIN 语句显示在我实际得到结果的情况下使用文件排序而不是索引。原始查询如下所示:
修改后的工作查询如下所示:
以下是表格定义:
CREATE TABLE IF NOT EXISTS `c_stocks` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`id_stock_type` int(10) unsigned DEFAULT NULL,
`name` varchar(255) DEFAULT NULL,
`locality` varchar(100) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `StockType_idx` (`id_stock_type`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE IF NOT EXISTS `g_locations` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
`ref_type` enum('stock','object','branch') DEFAULT NULL,
`ref_id` int(10) unsigned DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `UniqueLocation` (`ref_type`,`ref_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
ref_id
字段包含我在此定义中省略的长注释。
【问题讨论】:
尝试在sqlfiddle.com中提供一些数据 好点。这让我意识到我在 mysql 5.6.12 中遇到了一个错误。 【参考方案1】:在 SQLFiddle.com 和我的第二台计算机上无法重现该错误后,我意识到一定存在错误。
确实,我使用的 5.6.12 版本存在这个错误:
某些使用 GROUP BY 的 LEFT JOIN 查询可能会返回不正确的结果。 (错误 #68897、错误 #16620047)
查看 MySQL 5.6.13 的变更日志:http://dev.mysql.com/doc/relnotes/mysql/5.6/en/news-5-6-13.html
升级到 5.6.17 解决了我的问题。我没有得到我期望的结果,独立于 ORDER 子句和聚合函数。
【讨论】:
【参考方案2】:删除
having locations.id is not null
改为使用
where locations.id is not null
locations.id 不为 null 对分组来说不是问题 - 您根本不希望包含它们。
另外,您需要对locations.id 做一些事情,因为它不在group by 子句中。你想要“最大”位置.id 吗?
所以您的查询现在变为:
SELECT `Stocks`.`id` AS `Stocks.id` , max(`Locations`.`id`) AS `Locations.id`
FROM `rowiusnew`.`c_stocks` AS `Stocks`
LEFT JOIN `rowiusnew`.`g_locations` AS `Locations` ON ( `Locations`.`ref_id` = `Stocks`.`id` AND `Locations`.`ref_type` = 'stock' )
WHERE `Locations.id` IS NOT NULL
GROUP BY `Stocks`.`id`
进行这些更改,它应该更适合您。
仅供参考:我认为通过输入 order by 子句,您可以让引擎猜测您想要的位置。id,否则它没有任何线索。在 MYSQL 之外的其他东西中,它根本不会运行。
【讨论】:
确实,聚合函数会输出正确的结果。但是,您对 MySQL 必须猜测的断言是错误的。请注意,ref_id 和 ref_type 上有一个 UNIQUE 索引,它将最大匹配行数限制为 1。以上是关于SELECT 查询不返回没有 ORDER BY 子句的结果的主要内容,如果未能解决你的问题,请参考以下文章
在 group by 中使用 datetime 日期并在单个 SELECT 中使用 order by 与使用子查询