假设一个表CAR
有两列CAR_ID (int)
和VERSION (int)
。
我想检索每辆车的最高版本。
所以有两种解决方案(至少):
select car_id, max(version) as max_version
from car
group by car_id;
或者:
select car_id, max_version
from ( select car_id, version
, max(version) over (partition by car_id) as max_version
from car
) max_ver
where max_ver.version = max_ver.max_version
这两个查询的表现是否相似?
答案 0 :(得分:3)
我知道这是非常古老但我们应该指出。
select car_id, max_version
from (select car_id
, version
, max(version) over (partition by car_id) as max_version
from car ) max_ver
where max_ver.version = max_ver.max_version
不确定为什么你做了那样的选项二......在这种情况下,子选择在理论上应该更慢,因为你从同一个表中选择2x然后将结果加回到自身。
只需从内联视图中删除版本,它们就是一样的。
select car_id, max(version) over (partition by car_id) as max_version
from car
在这种情况下,性能实际上取决于优化器,但是原来的答案显示内联视图,因为它们会缩小结果。虽然这不是一个很好的例子,因为它的相同表格在给定的选择中没有过滤器。
当您选择许多列但需要适合结果集的不同聚合时,分区也很有用。否则,您被迫按其他列分组。
答案 1 :(得分:2)
是可能会影响
第二个查询是内联视图的示例。 这是一种非常有用的方法,可以使用各种类型的计数或使用任何聚合函数来执行报告。
Oracle执行子查询,然后将结果行用作FROM子句中的视图。
在我们考虑性能时,始终建议使用内联视图,而不是选择其他子查询类型。
还有一个问题是第二个查询会给出所有最大记录,而第一个查询只会给你一个最大记录。
答案 2 :(得分:2)
这取决于您的索引方案和表中的数据量。优化器可能会根据表中实际存在的数据做出不同的决策。
我发现,至少在SQL Server中(我知道你问过Oracle)优化器更有可能使用PARTITION BY查询和GROUP BY查询执行完整扫描。但这只是在你有一个包含CAR_ID和VERSION(DESC)的索引的情况下。
故事的寓意是我会彻底测试选择正确的故事。对于小桌子,没关系。对于真正的,非常大的数据集,两者都不会很快......