我有这个问题:
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子句中有两个条件。更改或删除大括号或更改这些条件的顺序不会改变结果。
通常,您会怀疑id
中的字段g_locations
有时为NULL,因此ORDER BY子句使正确的引用结果显示在组数据集的“顶部”。不是这种情况; id
字段已正确设置为主键字段并使用auto_increment。
EXPLAIN语句显示在实际获得结果的情况下,使用filesort而不是索引。原始查询如下所示:
修改后的工作查询如下所示:
以下是表格定义:
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
字段包含我在此定义中省略的长注释。
答案 0 :(得分:1)
在无法在SQLFiddle.com和我的第二台计算机上重现错误之后,我意识到必须涉及到一个错误。
实际上,我使用的5.6.12版本存在这个错误:
使用GROUP BY的某些LEFT JOIN查询可能会返回不正确的结果。 (Bug#68897,Bug#16620047)
请参阅MySQL 5.6.13的更改日志:http://dev.mysql.com/doc/relnotes/mysql/5.6/en/news-5-6-13.html
升级到5.6.17解决了我的问题。我没有得到我期望的结果,独立于ORDER子句和聚合函数。
答案 1 :(得分:0)
删除
having locations.id is not null
改为使用
where locations.id is not null
locations.id不为null对于分组来说不是问题 - 您根本不希望它们被包含在内。
此外,您需要对locations.id执行某些操作,因为它不在group by子句中。你想要“max”locations.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子句,你允许引擎猜测你想要的locations.id,否则它没有任何线索。在MYSQL以外的东西中,它根本不会运行。