Day 62:SELECT ― 欲しいデータだけ、きれいに取り出す
Day 62では、SQLの中でもいちばんよく使う主役たち―― SELECT / WHERE / ORDER BY / LIMIT をまとめて扱っていきます。
昨日までで「テーブル」「レコード」「カラム」という世界観はつかめてきました。 今日はそこに、「どうやって欲しいデータだけを取り出すか」 という視点を乗せていきます。
- SELECT:どのカラムを取り出すか
- WHERE:どんな条件で絞り込むか
- ORDER BY:どんな順番で並べるか
- LIMIT:何件まで取り出すか
この4つを組み合わせられるようになると、 データベースの中の情報が、ぐっと「自分の道具」っぽく感じられるようになります。
SELECTの基本 ― 「どのカラムを見たいか」を伝える
まずは一番シンプルな SELECT
例として、Day 61で作った users テーブルを使います。
SELECT id, name, email, age FROM users;
これは、
users テーブルから、id・name・email・age カラムを全部取り出してね
という意味です。
Python+SQLiteで書くと、こんな感じになります。
# day62_select_basic.py
import sqlite3
from pathlib import Path
def get_connection(db_name: str = "day61_example.db") -> sqlite3.Connection:
"""
SQLiteデータベースに接続するための関数です。
すでに Day 61 で作った DB を再利用します。
"""
return sqlite3.connect(Path(db_name))
def select_all_users(conn: sqlite3.Connection) -> None:
"""
users テーブルから全ユーザーを SELECT する基本例です。
"""
print("=== 全ユーザーを取得します(SELECT 基本) ===")
sql = "SELECT id, name, email, age FROM users;"
cur = conn.cursor()
cur.execute(sql)
rows = cur.fetchall()
for row in rows:
# row は (id, name, email, age) のタプルです。
print(f"id={row[0]}, name={row[1]}, email={row[2]}, age={row[3]}")
if __name__ == "__main__":
conn = get_connection()
select_all_users(conn)
conn.close()
PythonSELECT * は「全部ください」
よく出てくる書き方に、SELECT * があります。
SELECT * FROM users;
これは、
users テーブルのすべてのカラムを取り出してね
という意味です。
便利ですが、「どのカラムを使っているか」がコードから見えにくくなるので、 学習中はなるべくカラム名を明示する ほうが理解が深まりやすいです。
WHEREで絞り込む ― 「条件に合うレコードだけ欲しい」
WHEREの基本形
次に、WHERE で条件をつけて絞り込む ことを考えます。
例えば、
年齢が 25 以上のユーザーだけ欲しい
という場合は、こう書きます。
SELECT id, name, email, age
FROM users
WHERE age >= 25;
Pythonで実行してみましょう。
# day62_where_basic.py
import sqlite3
from pathlib import Path
def get_connection(db_name: str = "day61_example.db") -> sqlite3.Connection:
return sqlite3.connect(Path(db_name))
def select_users_age_over_25(conn: sqlite3.Connection) -> None:
"""
WHERE を使って、年齢が 25 以上のユーザーだけを取得する例です。
"""
print("=== 年齢が 25 以上のユーザーを取得します(WHERE 基本) ===")
sql = """
SELECT id, name, email, age
FROM users
WHERE age >= 25;
"""
cur = conn.cursor()
cur.execute(sql)
rows = cur.fetchall()
for row in rows:
print(f"id={row[0]}, name={row[1]}, email={row[2]}, age={row[3]}")
if __name__ == "__main__":
conn = get_connection()
select_users_age_over_25(conn)
conn.close()
Pythonプレースホルダで「条件値」を変えられるようにする
実際のツールでは、「25 固定」ではなく、 ユーザーが指定した値で絞り込みたい 場面が多いですよね。
そんなときは、Python側の値をプレースホルダ ? に渡します。
def select_users_age_over(conn: sqlite3.Connection, min_age: int) -> None:
"""
min_age 以上のユーザーを取得する、柔軟な WHERE の例です。
"""
print(f"=== 年齢が {min_age} 以上のユーザーを取得します ===")
sql = """
SELECT id, name, email, age
FROM users
WHERE age >= ?;
"""
cur = conn.cursor()
# ? に min_age を差し込みます。
cur.execute(sql, (min_age,))
rows = cur.fetchall()
for row in rows:
print(f"id={row[0]}, name={row[1]}, email={row[2]}, age={row[3]}")
Pythonここがとても大事なポイントです。
- 文字列連結で
"... WHERE age >= " + str(min_age)のように書くと、 SQLインジェクションなどの危険につながることがあります。 ?プレースホルダ+execute(sql, (値,))の形を習慣にしておくと、 安全で読みやすいコードになりやすいです。
ORDER BYで並べ替える ― 「順番をコントロールする」
ORDER BYの基本形
次は、ORDER BY で並べ替え をしてみます。
例えば、
年齢の若い順に並べたい
という場合は、こう書きます。
SELECT id, name, email, age
FROM users
ORDER BY age ASC;
ASCは昇順(小さい値から大きい値へ)DESCは降順(大きい値から小さい値へ)
Pythonで試してみましょう。
# day62_order_by_basic.py
import sqlite3
from pathlib import Path
def get_connection(db_name: str = "day61_example.db") -> sqlite3.Connection:
return sqlite3.connect(Path(db_name))
def select_users_order_by_age(conn: sqlite3.Connection, descending: bool = False) -> None:
"""
ORDER BY を使って、年齢順にユーザーを並べる例です。
descending=True なら降順、False なら昇順になります。
"""
order = "DESC" if descending else "ASC"
print(f"=== 年齢順({order})でユーザーを取得します ===")
sql = f"""
SELECT id, name, email, age
FROM users
ORDER BY age {order};
"""
cur = conn.cursor()
cur.execute(sql)
rows = cur.fetchall()
for row in rows:
print(f"id={row[0]}, name={row[1]}, email={row[2]}, age={row[3]}")
PythonORDER BY+WHERE の組み合わせ
もちろん、絞り込み+並べ替え もできます。
年齢が 20 以上のユーザーを、年齢の高い順に並べたい
SELECT id, name, email, age
FROM users
WHERE age >= 20
ORDER BY age DESC;
このように、 WHERE → ORDER BY の順で書くのが基本形です。
LIMITで件数を絞る ― 「とりあえず上位だけ見たい」
LIMITの基本形
最後に、LIMIT で「何件まで」取り出すかを制限する ことを考えます。
例えば、
ユーザーを年齢の高い順に並べて、上位3件だけ見たい
という場合は、こう書きます。
SELECT id, name, email, age
FROM users
ORDER BY age DESC
LIMIT 3;
Pythonで書くと、こんな感じです。
# day62_limit_basic.py
import sqlite3
from pathlib import Path
def get_connection(db_name: str = "day61_example.db") -> sqlite3.Connection:
return sqlite3.connect(Path(db_name))
def select_top_n_by_age(conn: sqlite3.Connection, n: int) -> None:
"""
ORDER BY と LIMIT を組み合わせて、
年齢の高い順に上位 n 件だけ取得する例です。
"""
print(f"=== 年齢の高い順に上位 {n} 件のユーザーを取得します ===")
sql = """
SELECT id, name, email, age
FROM users
ORDER BY age DESC
LIMIT ?;
"""
cur = conn.cursor()
cur.execute(sql, (n,))
rows = cur.fetchall()
for row in rows:
print(f"id={row[0]}, name={row[1]}, email={row[2]}, age={row[3]}")
PythonLIMITは「お試し」「プレビュー」にも便利
LIMITは、データが大量にあるときに、
- とりあえず上位10件だけ見たい
- ちゃんと取れているか、少しだけ確認したい
というときに、とても重宝します。
SELECT+WHERE+ORDER BY+LIMITをまとめて使う
ここまでの4つを、ひとつの関数にまとめてみます。
条件付きで絞り込み → 並べ替え → 上位だけ取得
という、よくあるパターンです。
# day62_select_combo.py
import sqlite3
from pathlib import Path
def get_connection(db_name: str = "day61_example.db") -> sqlite3.Connection:
return sqlite3.connect(Path(db_name))
def select_users_advanced(
conn: sqlite3.Connection,
min_age: int,
limit: int,
descending: bool = True,
) -> None:
"""
SELECT / WHERE / ORDER BY / LIMIT を組み合わせた例です。
- min_age 以上のユーザーを対象に
- 年齢順(昇順 or 降順)に並べて
- 上位 limit 件だけ取得します
"""
order = "DESC" if descending else "ASC"
print(
f"=== 年齢 >= {min_age}, 年齢順({order}), 上位 {limit} 件のユーザーを取得します ==="
)
sql = f"""
SELECT id, name, email, age
FROM users
WHERE age >= ?
ORDER BY age {order}
LIMIT ?;
"""
cur = conn.cursor()
# WHERE の ? に min_age、LIMIT の ? に limit を渡します。
cur.execute(sql, (min_age, limit))
rows = cur.fetchall()
for row in rows:
print(f"id={row[0]}, name={row[1]}, email={row[2]}, age={row[3]}")
def main():
conn = get_connection()
# 例: 年齢 20 以上、年齢の高い順に上位 2 件だけ取得
select_users_advanced(conn, min_age=20, limit=2, descending=True)
conn.close()
if __name__ == "__main__":
main()
Pythonこのくらい書けるようになると、 「欲しいデータだけを、欲しい順番で、欲しい件数だけ取り出す」 という、データベースらしい操作がかなり自由にできるようになってきます。
Day 62ミニテンプレート:SELECT基礎セット
最後に、Day 62の内容をぎゅっとまとめた SELECT基礎テンプレート を載せておきます。
# day62_select_template.py
import sqlite3
from pathlib import Path
def get_connection(db_name: str = "day61_example.db") -> sqlite3.Connection:
return sqlite3.connect(Path(db_name))
def select_all(conn: sqlite3.Connection) -> list[tuple]:
sql = "SELECT id, name, email, age FROM users;"
cur = conn.cursor()
cur.execute(sql)
return cur.fetchall()
def select_where_age_over(conn: sqlite3.Connection, min_age: int) -> list[tuple]:
sql = """
SELECT id, name, email, age
FROM users
WHERE age >= ?;
"""
cur = conn.cursor()
cur.execute(sql, (min_age,))
return cur.fetchall()
def select_order_by_age(conn: sqlite3.Connection, descending: bool = False) -> list[tuple]:
order = "DESC" if descending else "ASC"
sql = f"""
SELECT id, name, email, age
FROM users
ORDER BY age {order};
"""
cur = conn.cursor()
cur.execute(sql)
return cur.fetchall()
def select_top_n_by_age(conn: sqlite3.Connection, n: int) -> list[tuple]:
sql = """
SELECT id, name, email, age
FROM users
ORDER BY age DESC
LIMIT ?;
"""
cur = conn.cursor()
cur.execute(sql, (n,))
return cur.fetchall()
def main():
conn = get_connection()
print("=== 全件 ===")
for row in select_all(conn):
print(row)
print("\n=== 年齢 >= 25 ===")
for row in select_where_age_over(conn, 25):
print(row)
print("\n=== 年齢昇順 ===")
for row in select_order_by_age(conn, descending=False):
print(row)
print("\n=== 年齢上位 2 件 ===")
for row in select_top_n_by_age(conn, 2):
print(row)
conn.close()
if __name__ == "__main__":
main()
PythonDay 62のまとめ ― 「欲しいデータだけ」を取り出せると、世界が一気に広がる
今日扱ったキーワードは、
- SELECT:どのカラムを取り出すか
- WHERE:どんな条件で絞り込むか
- ORDER BY:どんな順番で並べるか
- LIMIT:何件まで取り出すか
でした。
この4つを組み合わせられるようになると、
- 「特定の条件に合うユーザーだけを抽出する」
- 「スコアの高い順に上位10件だけ見る」
- 「最近のデータだけを確認する」
といった操作が、ぐっと自然に書けるようになります。
データベースの中の情報が、 ただ「しまわれているだけのもの」から、 「必要なときに、必要な形で取り出せる道具」 に変わっていく瞬間です。
