Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/60.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Mysql AR-过滤器组查询_Mysql_Sql_Ruby On Rails_Ruby_Activerecord - Fatal编程技术网

Mysql AR-过滤器组查询

Mysql AR-过滤器组查询,mysql,sql,ruby-on-rails,ruby,activerecord,Mysql,Sql,Ruby On Rails,Ruby,Activerecord,我试图弄清楚为什么我的查询没有按我希望的方式运行。以下声明旨在为每款福特车型提供最新的库存: Car.where("make = 'Ford'").group(:model_id).having('year = MAX(year)') 但它似乎是根据模型id进行分组,然后根据年份对所有数据进行过滤,而不仅仅是针对每个组。这是它正在生成的SQL: SELECT `cars`.* FROM `cars` WHERE `cars`.`make` = 'Ford' GROUP BY model_id

我试图弄清楚为什么我的查询没有按我希望的方式运行。以下声明旨在为每款福特车型提供最新的库存:

Car.where("make = 'Ford'").group(:model_id).having('year = MAX(year)')
但它似乎是根据模型id进行分组,然后根据年份对所有数据进行过滤,而不仅仅是针对每个组。这是它正在生成的SQL:

SELECT `cars`.* FROM `cars` WHERE `cars`.`make` = 'Ford' GROUP BY model_id HAVING year = MAX(year)
我做错了什么?我是否可以使用其他查询

更新

以下是数据示例:

| make | model_id | year |
| Ford | 1        | 2000 |
| Ford | 1        | 2002 |
| Ford | 1        | 2010 |
| Ford | 2        | 2012 |
| BMW  | 3        | 2012 |
| BMW  | 4        | 2014 |
并且在查询后应返回以下内容:

| Ford | 1        | 2010 |
| Ford | 2        | 2012 |

您还可以将聚合函数用作SELECT子句的一部分,这将产生所需的结果:

cars = Car.select('MAX(year)').group(:model_id)
cars.to_a.last.attributes
#=> {name: 'BMW', model_id: 4, ..., max: 2014}
可以使用别名一次选择多个聚合:

cars = Car.select('MAX(year) as max_year, MAX(hp) as max_hp').group(:model_id)
cars.to_a.last.attributes
#=> {name: 'BMW', model_id: 4, ..., max_year: 2014, max_hp: 120}
在Postgresql中,在组中查找极端值。这不是很漂亮,但结果是一个适当的ActiveRecord关系,可以与其他作用域链接:

Car.from('(SELECT *, rank() OVER (PARTITION BY model_id ORDER BY year DESC) FROM cars) AS cars').where('rank = 1')
为了便于阅读,可以对其进行一些重构:

partition = 'PARTITION BY model_id ORDER BY year DESC'
subquery = Car.arel_table.project("*, rank() OVER (#{partition})")
Car.from("(#{subquery}) AS cars").where('rank = 1')
现在,您甚至可以为每组购买两辆最新的汽车:

Car.from("(#{subquery}) AS cars").where('rank <= 2')

首先,您的预期结果是不可能的-您声明查询是针对Fords的,但您在结果中预期的是BMW的。我假设这是一个剪切粘贴错误

您面临的问题是,您需要告诉having子句更多关于查询的信息,即您感兴趣的每组数据的maxyear

在mysql中提取所需结果的sql查询如下所示:

mysql> select make, model, max(year) as 'year' from cars group by model having year=max(year);
结果:

+------+-------+------+
| make | model | year |
+------+-------+------+
| Ford |     1 | 2010 |
| Ford |     2 | 2012 |
| BMW  |     3 | 2012 |
| BMW  |     4 | 2014 |
+------+-------+------+
将其转换为活动记录时,您需要如下查询:

Car.select('make, model, max(year) as year').group(:model).having('year = max(year)')
仅适用于福特:

Car.select('make, model, max(year) as year').where(:model=>'Ford').group(:model).having('year = max(year)')

感谢@p11y发布了一个链接,帮助我通过以下查询解决了问题。注意:它可能不是最有效的。如果愿意,请提供更有效的查询

subquery = "select max(year) from cars as c where c.model_id = cars.model_id"
Car.where("make = 'Ford' AND year = (#{subquery})")

更新:添加子查询以使其更易于阅读。

BMW结果是一个错误,对此表示抱歉。如果您只想获得Ford怎么办?@ArtemKalinchuk在选择块后添加一个where:model=>“Ford”,它需要是一个关系。我不想要数组。@ArtemKalinchuk检查我的编辑,你可以在Postgres中使用窗口函数。对不起,我没有mysql的经验。我必须用谷歌搜索它,但我相信你自己也能做到:你可能想读这篇文章: