単一のテーブルからデータをクエリする
このドキュメントでは、SQL とさまざまなプログラミング言語を使用して、データベース内の単一のテーブルからデータをクエリする方法について説明します。
あなたが始める前に
次のコンテンツでは、 書店アプリケーションを例に、TiDB 内の単一のテーブルからデータをクエリする方法を示します。
データをクエリする前に、次の手順が完了していることを確認してください。
- TiDB クラスターを構築します ( TiDB CloudまたはTiUPの使用を推奨)。
簡単なクエリを実行する
Bookshop アプリケーションのデータベースでは、 authors
テーブルに著者の基本情報が格納されています。3 SELECT ... FROM ...
ステートメントを使用して、データベースからデータを照会できます。
- SQL
- Java
MySQL クライアントで次の SQL ステートメントを実行します。
SELECT id, name FROM authors;
出力は次のようになります。
+------------+--------------------------+
| id | name |
+------------+--------------------------+
| 6357 | Adelle Bosco |
| 345397 | Chanelle Koepp |
| 807584 | Clementina Ryan |
| 839921 | Gage Huel |
| 850070 | Ray Armstrong |
| 850362 | Ford Waelchi |
| 881210 | Jayme Gutkowski |
| 1165261 | Allison Kuvalis |
| 1282036 | Adela Funk |
...
| 4294957408 | Lyla Nitzsche |
+------------+--------------------------+
20000 rows in set (0.05 sec)
Javaでは、著者の基本情報を格納するために、クラスAuthor
を宣言できます。データベースのデータ型と値の範囲に応じて適切なJavaデータ型を選択する必要があります。例:
- タイプ
int
のデータを格納するには、タイプInt
の変数を使用します。 - タイプ
bigint
のデータを格納するには、タイプLong
の変数を使用します。 - タイプ
tinyint
のデータを格納するには、タイプShort
の変数を使用します。 - タイプ
varchar
のデータを格納するには、タイプString
の変数を使用します。
public class Author {
private Long id;
private String name;
private Short gender;
private Short birthYear;
private Short deathYear;
public Author() {}
// Skip the getters and setters.
}
public class AuthorDAO {
// Omit initialization of instance variables.
public List<Author> getAuthors() throws SQLException {
List<Author> authors = new ArrayList<>();
try (Connection conn = ds.getConnection()) {
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("SELECT id, name FROM authors");
while (rs.next()) {
Author author = new Author();
author.setId(rs.getLong("id"));
author.setName(rs.getString("name"));
authors.add(author);
}
}
return authors;
}
}
- JDBC ドライバーを使用して TiDB に接続するの後は
conn.createStatus()
でStatement
オブジェクトを作成できます。
- 次に、
stmt.executeQuery("query_sql")
呼び出して、TiDB へのデータベース クエリ要求を開始します。 - クエリの結果は
ResultSet
オブジェクトに保存されます。ResultSet
トラバースすると、返された結果をAuthor
オブジェクトにマッピングできます。
結果をフィルタリング
クエリ結果をフィルタリングするには、 WHERE
ステートメントを使用できます。
たとえば、次のコマンドは、すべての著者の中から 1998 年に生まれた著者を照会します。
- SQL
- Java
WHERE
ステートメントにフィルター条件を追加します。
SELECT * FROM authors WHERE birth_year = 1998;
Javaでは、同じ SQL を使用して、動的パラメータを含むデータ クエリ要求を処理できます。
これは、パラメータを SQL ステートメントに連結することで実行できます。ただし、この方法はアプリケーションのセキュリティに潜在的SQLインジェクションリスクをもたらします。
このようなクエリを処理するには、通常のステートメントの代わりに準備された声明を使用します。
public List<Author> getAuthorsByBirthYear(Short birthYear) throws SQLException {
List<Author> authors = new ArrayList<>();
try (Connection conn = ds.getConnection()) {
PreparedStatement stmt = conn.prepareStatement("""
SELECT * FROM authors WHERE birth_year = ?;
""");
stmt.setShort(1, birthYear);
ResultSet rs = stmt.executeQuery();
while (rs.next()) {
Author author = new Author();
author.setId(rs.getLong("id"));
author.setName(rs.getString("name"));
authors.add(author);
}
}
return authors;
}
結果を並べ替える
クエリ結果を並べ替えるには、 ORDER BY
ステートメントを使用できます。
たとえば、次の SQL ステートメントは、 authors
テーブルをbirth_year
列に従って降順 ( DESC
) で並べ替えて、最も若い著者のリストを取得します。
- SQL
- Java
SELECT id, name, birth_year
FROM authors
ORDER BY birth_year DESC;
public List<Author> getAuthorsSortByBirthYear() throws SQLException {
List<Author> authors = new ArrayList<>();
try (Connection conn = ds.getConnection()) {
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("""
SELECT id, name, birth_year
FROM authors
ORDER BY birth_year DESC;
""");
while (rs.next()) {
Author author = new Author();
author.setId(rs.getLong("id"));
author.setName(rs.getString("name"));
author.setBirthYear(rs.getShort("birth_year"));
authors.add(author);
}
}
return authors;
}
結果は以下のようになります。
+-----------+------------------------+------------+
| id | name | birth_year |
+-----------+------------------------+------------+
| 83420726 | Terrance Dach | 2000 |
| 57938667 | Margarita Christiansen | 2000 |
| 77441404 | Otto Dibbert | 2000 |
| 61338414 | Danial Cormier | 2000 |
| 49680887 | Alivia Lemke | 2000 |
| 45460101 | Itzel Cummings | 2000 |
| 38009380 | Percy Hodkiewicz | 2000 |
| 12943560 | Hulda Hackett | 2000 |
| 1294029 | Stanford Herman | 2000 |
| 111453184 | Jeffrey Brekke | 2000 |
...
300000 rows in set (0.23 sec)
クエリ結果の数を制限する
クエリ結果の数を制限するには、 LIMIT
ステートメントを使用できます。
- SQL
- Java
SELECT id, name, birth_year
FROM authors
ORDER BY birth_year DESC
LIMIT 10;
public List<Author> getAuthorsWithLimit(Integer limit) throws SQLException {
List<Author> authors = new ArrayList<>();
try (Connection conn = ds.getConnection()) {
PreparedStatement stmt = conn.prepareStatement("""
SELECT id, name, birth_year
FROM authors
ORDER BY birth_year DESC
LIMIT ?;
""");
stmt.setInt(1, limit);
ResultSet rs = stmt.executeQuery();
while (rs.next()) {
Author author = new Author();
author.setId(rs.getLong("id"));
author.setName(rs.getString("name"));
author.setBirthYear(rs.getShort("birth_year"));
authors.add(author);
}
}
return authors;
}
結果は以下のようになります。
+-----------+------------------------+------------+
| id | name | birth_year |
+-----------+------------------------+------------+
| 83420726 | Terrance Dach | 2000 |
| 57938667 | Margarita Christiansen | 2000 |
| 77441404 | Otto Dibbert | 2000 |
| 61338414 | Danial Cormier | 2000 |
| 49680887 | Alivia Lemke | 2000 |
| 45460101 | Itzel Cummings | 2000 |
| 38009380 | Percy Hodkiewicz | 2000 |
| 12943560 | Hulda Hackett | 2000 |
| 1294029 | Stanford Herman | 2000 |
| 111453184 | Jeffrey Brekke | 2000 |
+-----------+------------------------+------------+
10 rows in set (0.11 sec)
この例では、 LIMIT
ステートメントにより、クエリ時間が0.23 sec
から0.11 sec
に大幅に短縮されます。詳細については、 TopNと制限を参照してください。
集計クエリ
全体的なデータ状況をよりよく理解するために、 GROUP BY
ステートメントを使用してクエリ結果を集計できます。
たとえば、どの年に作家がより多く生まれたかを知りたい場合は、 authors
テーブルをbirth_year
の列でグループ化し、各年をカウントします。
- SQL
- Java
SELECT birth_year, COUNT (DISTINCT id) AS author_count
FROM authors
GROUP BY birth_year
ORDER BY author_count DESC;
public class AuthorCount {
private Short birthYear;
private Integer authorCount;
public AuthorCount() {}
// Skip the getters and setters.
}
public List<AuthorCount> getAuthorCountsByBirthYear() throws SQLException {
List<AuthorCount> authorCounts = new ArrayList<>();
try (Connection conn = ds.getConnection()) {
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("""
SELECT birth_year, COUNT(DISTINCT id) AS author_count
FROM authors
GROUP BY birth_year
ORDER BY author_count DESC;
""");
while (rs.next()) {
AuthorCount authorCount = new AuthorCount();
authorCount.setBirthYear(rs.getShort("birth_year"));
authorCount.setAuthorCount(rs.getInt("author_count"));
authorCounts.add(authorCount);
}
}
return authorCount;
}
結果は以下のようになります。
+------------+--------------+
| birth_year | author_count |
+------------+--------------+
| 1932 | 317 |
| 1947 | 290 |
| 1939 | 282 |
| 1935 | 289 |
| 1968 | 291 |
| 1962 | 261 |
| 1961 | 283 |
| 1986 | 289 |
| 1994 | 280 |
...
| 1972 | 306 |
+------------+--------------+
71 rows in set (0.00 sec)
COUNT
関数に加えて、TiDB は他の集計関数もサポートしています。詳細については、 集計 (GROUP BY) 関数を参照してください。