15. SQLで記述
SELECT
actresses.*
FROM
actresses
INNER JOIN (
SELECT
"movies"."actress_id" AS actress_id,
MAX(year) AS max_year
FROM
"movies"
GROUP BY
"movies"."actress_id"
) AS movies_max_year
ON actresses.id = movies_max_year.actress_id
ORDER BY max_year DESC, actresses.id ASC
actress_id | max_year
------------+----------
5 | 2013
4 | 2013
2 | 2016
1 | 2006
id | name
----+------------
1 | 多部未華子
2 | 佐津川愛美
3 | 新垣結衣
4 | 堀北真希
5 | 吉高由里子
6 | 悠城早矢
id | name
----+------------
2 | 佐津川愛美
4 | 堀北真希
5 | 吉高由里子
1 | 多部未華子
0
*
0
*
actressesmovies_max_year
16. ActiveRecordで記述(find_by_sql)
Actress.find_by_sql(%|
SELECT
actresses.*
FROM
actresses
INNER JOIN (
SELECT
"movies"."actress_id" AS actress_id,
MAX(year) AS max_year
FROM
"movies"
GROUP BY
"movies"."actress_id"
) AS movies_max_year
ON actresses.id = movies_max_year.actress_id
ORDER BY max_year DESC, actresses.id ASC
|)
➢ Arrayで出力
➢ Kaminariが使えない
○ Kaminari.paginate_arrayを使えばArrayでも使える
が、scopeで使いたい。
[#<Actress:0x007f8978525928
id: 2,
name: "佐津川愛美 ">,
#<Actress:0x007f8972e37968
id: 4,
name: "堀北真希">,
#<Actress:0x007f897851d0c0
id: 5,
name: "吉高由里子 ">,
#<Actress:0x007f897850fd58
id: 1,
name: "多部未華子 ">]
0
*
0
*
17. ActiveRecordで記述(Arelを使う)
SELECT
actresses.*
FROM
actresses
INNER JOIN (
SELECT
"movies"."actress_id" AS actress_id,
MAX(year) AS max_year
FROM
"movies"
GROUP BY
"movies"."actress_id"
) AS movies_max_year
ON actresses.id = movies_max_year.actress_id
ORDER BY max_year DESC, actresses.id ASC
actress_at = Actress.arel_table
movie_at = Movie.arel_table
movies_max_year = movie_at.project(
Arel.sql(%|
"movies"."actress_id" as actress_id,
MAX(year) as max_year
|)
).group("movies.actress_id").as("movies_max_year")
join_conds = actress_at.join(
movies_max_year,
Arel::Nodes::InnerJoin
).on(
movies_max_year[:actress_id].eq(actress_at[:id])
).join_sources
Actress.joins(join_conds).order("movies_max_year.max_year DESC")
0
*
0
*
18. ActiveRecordで記述(joinsの中にSQL直書き)
SELECT
actresses.*
FROM
actresses
INNER JOIN (
SELECT
"movies"."actress_id" AS actress_id,
MAX(year) AS max_year
FROM
"movies"
GROUP BY
"movies"."actress_id"
) AS movies_max_year
ON actresses.id = movies_max_year.actress_id
ORDER BY max_year DESC, actresses.id ASC
Actress.joins(%|
INNER JOIN (
SELECT
"movies"."actress_id" AS actress_id,
MAX(year) AS max_year
FROM
"movies"
GROUP BY
"movies"."actress_id"
) AS movies_max_year
ON actresses.id = movies_max_year.actress_id
|).order("max_year desc, actresses.id asc")
0
*
0
*
19. scopeにして
class Actress < ApplicationRecord
scope :order_by_movie_year, -> {
actress_at = arel_table
movie_at = Movie.arel_table
movies_max_year = movie_at.project(
Arel.sql(%|
"movies"."actress_id" as actress_id,
MAX(year) as max_year
|)
).group("movies.actress_id").as("movies_max_year")
join_conds = actress_at.join(
movies_max_year,
Arel::Nodes::InnerJoin
).on(
movies_max_year[:actress_id].eq(actress_at[:id])
).join_sources
joins(join_conds).order("movies_max_year.max_year DESC")
}
end
pry> Actress.order_by_movie_year.class
=> Actress::ActiveRecord_Relation
scope :order_by_movie_year, -> {
joins(%|
INNER JOIN (
SELECT
"movies"."actress_id" AS actress_id,
MAX(year) AS max_year
FROM
"movies"
GROUP BY
"movies"."actress_id"
) AS movies_max_year
ON actresses.id = movies_max_year.actress_id
|).order("max_year DESC, actresses.id ASC")
}
0
*
0
*