CodeGym /コース /SQL SELF /配列を使った複雑なクエリ例:集約、フィルタリング、ソート

配列を使った複雑なクエリ例:集約、フィルタリング、ソート

SQL SELF
レベル 36 , レッスン 3
使用可能

配列を使った複雑なクエリ例:集約、フィルタリング、ソート

今日は、SQLのクエリで配列をどう使いこなすかを見ていくよ。値をグループ化したり、中身でフィルタしたり、配列の中で直接ソートしたり。これ、ただの理論じゃなくて、レポートや分析、パーソナライズとか、現場でガチで使うテク。コツさえ掴めば超簡単!今から一緒にやってみよう。

配列でデータを集約する

配列の真価が発揮されるのは、データをグループ化したいとき。複数行をバラバラに取るんじゃなくて、欲しい値をひとつのキレイな配列にまとめちゃう。これで分析も楽だし、出力もスッキリ、余計なサブクエリも減る。実際にどうやるか見てみよう!

例1:array_agg()でデータを配列にまとめる

複数行の値をグループごとに配列にまとめたいときは、array_agg()が超便利。配列集約で一番使える関数だよ。

-- studentsテーブルがあって、id, name, courseのカラムがあるとする
CREATE TABLE students (
    id SERIAL PRIMARY KEY,
    name VARCHAR(100),
    course VARCHAR(100)
);

-- いくつかデータを挿入
INSERT INTO students (name, course) VALUES
('アリサ', '数学'),
('ボブ', '数学'),
('チャーリー', '物理'),
('デイブ', '物理'),
('エンマ', '数学');

-- コースごとに学生を配列でまとめる
SELECT course, array_agg(name) AS students
FROM students
GROUP BY course;

結果:

course students
数学 {アリサ, ボブ, エンマ}
物理 {チャーリー, デイブ}

配列にまとめると、例えばJSONでやりとりしたいときとか、データを簡単にパースできて超便利!

例2:ネストした配列を作る

もしもう一つテーブルがあって、2つのテーブルから配列を作りたい場合は?例えばcoursesテーブルで先生の情報を持ってるとしよう。

-- 先生のテーブルを作る
CREATE TABLE courses (
    id SERIAL PRIMARY KEY,
    name VARCHAR(100),
    teacher VARCHAR(100)
);

-- データを挿入
INSERT INTO courses (name, teacher) VALUES
('数学', 'プロフ・ミン'),
('物理', 'プロフ・ピーターソン');

-- ネストしたクエリで配列を作る
SELECT
    c.name AS course_name,
    array_agg(s.name) AS students,
    c.teacher
FROM
    courses c
LEFT JOIN
    students s
ON
    c.name = s.course
GROUP BY
    c.name, c.teacher;

結果:

course_name students teacher
数学 {アリサ, ボブ, エンマ} プロフ・ミン
物理 {チャーリー, デイブ} プロフ・ピーターソン

これで、コース・先生・学生が配列でまとまった便利なテーブルができた!

配列でデータをフィルタリングする

配列自体でも十分強力だけど、本当の魔法は配列を使ってデータをフィルタできること。例えば、興味リストに特定のワードがあるユーザーだけ選びたいとか、全ての価格がある閾値を超えてる注文だけ欲しいとか。全部SQLだけでできるから、アプリ側で余計なロジック書かなくてOK!

例1:配列の要素で行をフィルタする

例えば、配列に特定の値が含まれてる行だけ探したいとき。数学コースに登録してる学生を探す例を見てみよう。

-- `ANY`を使ってコースに登録してる学生をフィルタ
SELECT *
FROM students
WHERE course = ANY(ARRAY['数学', '物理']);

ここでANYは、値の配列を指定して、その中のどれかにcourseが一致する行を返してくれる。

例2:配列同士の重なりをチェック

今度はstudent_interestsテーブルがあって、学生の興味が配列で入ってるとしよう。自分の条件と重なってる学生を探したい場合はこうやる。

-- 学生の興味テーブルを作る
CREATE TABLE student_interests (
    id SERIAL PRIMARY KEY,
    name VARCHAR(100),
    interests TEXT[]
);

-- データを挿入
INSERT INTO student_interests (name, interests) VALUES
('アリサ', ARRAY['プログラミング', '音楽']),
('ボブ', ARRAY['スポーツ', 'プログラミング']),
('チャーリー', ARRAY['読書', '写真']),
('エンマ', ARRAY['音楽', 'スポーツ']);

-- プログラミングか音楽に興味ある学生を探す
SELECT *
FROM student_interests
WHERE interests && ARRAY['プログラミング', '音楽'];

&&演算子は、2つの配列の重なりをチェックする。左の配列のどれかが右の配列にあれば、その行はフィルタを通るよ。

結果:

id name interests
1 アリサ {プログラミング, 音楽}
2 ボブ {スポーツ, プログラミング}
4 エンマ {音楽, スポーツ}

配列のソート

配列の中の値の順番が大事なときもあるよね。特に、いろんな行から配列を作ったり、表示用にデータを整えたいとき。PostgreSQLなら、クエリの中で直接配列の要素をソートできる!

例1:配列の中身をソートする

配列の要素を並び替えたいとき。例えば、学生の興味をアルファベット順にソートしてみよう。

-- `array_sort()`で配列の要素をソート
SELECT 
    name,
    array_sort(interests) AS sorted_interests
FROM 
    student_interests;

結果:

name sorted_interests
アリサ {音楽, プログラミング}
ボブ {プログラミング, スポーツ}
チャーリー {写真, 読書}
エンマ {スポーツ, 音楽}

例2:配列の長さで行をソートする

今度は、興味の数が多い順に学生を並べたいとき。つまり、一番「熱中してる」学生から「ちょっと地味」な学生まで並べる感じ。

-- 配列の長さで行をソート
SELECT 
    name, 
    interests, 
    array_length(interests, 1) AS interests_count
FROM 
    student_interests
ORDER BY 
    interests_count DESC;

結果:

name interests interests_count
アリサ {プログラミング, 音楽} 2
ボブ {スポーツ, プログラミング} 2
チャーリー {読書, 写真} 2
エンマ {音楽, スポーツ} 2

この例だと全員興味の数は同じだけど、大きなテーブルならこのクエリを応用できるよ!

コメント
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION