基礎から学ぶPython入門 90日コース | データベース・Web API - Day 62:SELECT

Python 90日で身につけるPython
スポンサーリンク
スポンサーリンク

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()
Python

SELECT * は「全部ください」

よく出てくる書き方に、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]}")
Python

ORDER 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]}")
Python

LIMITは「お試し」「プレビュー」にも便利

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()
Python

Day 62のまとめ ― 「欲しいデータだけ」を取り出せると、世界が一気に広がる

今日扱ったキーワードは、

  • SELECT:どのカラムを取り出すか
  • WHERE:どんな条件で絞り込むか
  • ORDER BY:どんな順番で並べるか
  • LIMIT:何件まで取り出すか

でした。

この4つを組み合わせられるようになると、

  • 「特定の条件に合うユーザーだけを抽出する」
  • 「スコアの高い順に上位10件だけ見る」
  • 「最近のデータだけを確認する」

といった操作が、ぐっと自然に書けるようになります。

データベースの中の情報が、 ただ「しまわれているだけのもの」から、 「必要なときに、必要な形で取り出せる道具」 に変わっていく瞬間です。

タイトルとURLをコピーしました