質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

89.24%

Java/MySQL COUNT関数を使った際に取得が0になる

解決済

回答 8

投稿 編集

  • 評価
  • クリップ 4
  • VIEW 8,610

Richiko

score 19

前提・実現したいこと

Javaで住所録を作っています。  
名字の最初の一文字であ行~わ行に分け、さらに「あ行○件、か行○件~」と件数の表示をしたいです。

発生している問題

取得件数が0件となってしまいます。
どのようにしたら件数が正しく取得できるのか、お手数ですがご教示をお願いいたします。

追記

どうやらSQLは正しい値をとれているようです。
問題は変数countKanaに格納できていないところにあるようです。
わかる方、どうかご回答をお願いいたします。

情報

言語:Java
データベース:MySQL
userテーブル:
簡単ですがこんな感じに入っています。
+------------+---------+
| name       | initial |
+------------+---------+
| 山田花子  | や   |

 鈴木一郎    さ   

ソースコード

public int countKana(String initial) throws SQLException, ClassNotFoundException {

 Connection con = null;
 PreparedStatement pStm = null;
 int countKana = -1;

 try {

  /* DB接続 */
  Class.forName(bDAO.getDRIVER_NAME());
  con = DriverManager.getConnection(bDAO.getJDBC_URL(), bDAO.getDB_USER(), bDAO.getDB_PASS());

  /* SQL */
  String sql = "SELECT COUNT(*) AS countKana FROM user WHERE user.initial = '" + initial + "'";
  pStm = con.prepareStatement(sql);
  ResultSet rs = pStm.executeQuery();

  while (rs.next()) {
   countKana = rs.getInt("countKana");
  }

 } catch (Exception e) {
  e.printStackTrace();
  throw new SQLException(e);
 } finally {
  if (pStm != null) {
   try {
    pStm.close();
   } catch (Exception e) {
    e.printStackTrace();
    throw new SQLException(e);
   }
  }
  if (con != null) {
   try {
    con.close();
   } catch (Exception e) {
    e.printStackTrace();
    throw new SQLException(e);
   }
  }
 }

 return countKana;
}
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 8

checkベストアンサー

+3

Javaは詳しくないのですが、

while (rs.next())


これってひょっとして一行目スキップしちゃったりはしませんか?


元のSQLでも求める値を返していると思います。

SELECT COUNT(*) AS countKana FROM user WHERE user.initial = 'あ'


文字コードに問題なければ、直接DBで実行すれば「あ」の数が出力されるのでは無いでしょうか?

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/03/01 22:09

    こんばんは。

    本日、以下のようにgetConnectionの引数のJDBCのURLを訂正してみたところ、
    無事に値をとることができました。

    [修正前]
    jdbc:mysql://localhost/address

    [修正後]
    jdbc:mysql://localhost/address?useUnicode=true&characterEncoding=utf8

    原因はご指摘いただいた通り文字コードでした。
    大変助かりました、本当にありがとうございました!!

    キャンセル

  • 2016/03/01 22:16

    文字コードの件が出た時にやっぱりそこだなって思いました。
    無事解決できて良かったです。
    また、的外れな回答をして遠回りさせてしまい申し訳ありませんでした。

    キャンセル

  • 2016/03/01 22:27

    いえいえ、こちらこそ数日つきあわせてしまい申し訳なかったです;
    nabe3さんも誠にありがとうございました。

    キャンセル

+1

SELECT initial, COUNT(*)
  FROM users
 GROUP BY initial

でどうでしょうか?
initialでグループ化し、その件数を求めるSQLです。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/02/28 23:48

    同じコードで、SQLを以下のようにすると値が取れます。

    SELECT COUNT(*) AS countKana FROM user;

    なのでデータベースには接続できていると思います。

    でもSQLを変えると値が取れるということは、やはりSQLが悪いということでしょうか;

    キャンセル

  • 2016/02/29 00:11

    おそらくその通りだと思います。
    試しにSQL文組み立てる直前の行でデバッグ出力してみると
    (```System.out.println(initial);```)initial変数には何が格納されているのでしょうか

    キャンセル

  • 2016/02/29 00:43

    initialには「あ」の文字が入っています。
    メソッドを呼び出す際に引数として受け渡されるので、その他には「か」「さ」…などが入る形になります。

    コンソールにも、「あ」と表示されております。


    ****
    本日は遅くなりましたので、ここで休ませていただきます。
    質問をしている身でありながら申し訳ございません。
    引き続き明日の夜、ご質問をさせていただきたいと思います。
    どうかよろしくお願いいたします。

    キャンセル

+1

/* SQL */
  String sql = "SELECT COUNT(*) AS countKana FROM user WHERE user.initial = ?;"
  pStm = con.prepareStatement(sql);
  pStm.setString(initial);
  ResultSet rs = pStm.executeQuery();

prepareStatementつかうなら、SQL文の条件部分は「?」として、
パラメータをprepareStatementオブジェクトにセットしないとダメじゃないかな。

参考まで
https://docs.oracle.com/javase/jp/6/api/java/sql/PreparedStatement.html

あとちなみにですが、DB設計について
イニシャルカラムを持たせるなら
ふりがなカラムを持たせて前方一致検索するのも
良いかなと思いました。
(前方一致検索ならINDEXが効くはずなので)

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/03/01 22:16

    ありがとうございます。

    PrepareStatementに関しては仰るとおりで、私の間違った使用方法でした。
    ふりがなで前方一致検索は思いつきませんでした、ぜひ考えてみたいと思います。
    ご指摘ありがとうございます。

    また原因は文字コードが異なっていたからのようでした。
    ご尽力に感謝いたします、ありがとうございました。

    キャンセル

+1

hirohiroさんのおっしゃっている通り、文字コードの影響も大いにあり得ます。
また、別の可能性として…

メソッド定義でinitialを一つに限定していることから、下記の繰り返しは不要ではと感じます。
また、rs.getInt(int columnIndex)はcolumnIndex番目の項目のintデータを取得するメソッドです。
項目名での指定はエラーになるのではないのでしょうか?

/* 質問者ソースコピー */
  while (rs.next()) {
   countKana = rs.getInt("countKana");
  }



kurokoSinさんの回答に対するコメントで、SQL文が固まったようなのでそれを適用すると、
以下のようになるのではないでしょうか?

/* 例 */
 /* DB接続 */
  Class.forName(bDAO.getDRIVER_NAME());
  con = DriverManager.getConnection(bDAO.getJDBC_URL(), bDAO.getDB_USER(), bDAO.getDB_PASS());

  /* SQL */
  String sql = "SELECT COUNT(*) AS countDB FROM user GROUP BY initial HAVING initial = '" + initial + "'";

  pStm = con.prepareStatement(sql);
  ResultSet rs = pStm.executeQuery(); /* 実行の結果、1行だけの結果が返るはず… */

  rs.first(); /* カーソルを先頭に移動 */
  int columnIndex = 1;
  try { 
   /* sql実行結果、該当のイニシャルがある場合 */
   countKana = rs.getInt(columnIndex);
  } catch (Exception e) {
   /* sql実行結果、該当のイニシャルがない場合 */
   countKana = 0;
  }

以上、参考になりますでしょうか?

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/03/01 22:13

    ありがとうございます。
    値が返らない原因は、文字コードだったようです。

    rs.first()を使って値をとる方法は知らなかったので、大変勉強になります。
    こちらも活用させていただきます。

    誠にありがとうございました。

    キャンセル

0

あんまり自信が無いのですが・・・

while (rs.next()) {
   countKana = rs.getInt("countKana");
}


先にrs.next()を呼び出しているためではないかと思います。next(次は無いですから・・・)
countKana = rs.getInt("countKana");だけならどうでしょう?

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/02/28 21:43

    ご回答ありがとうございます。

    while(rs.next())を削除した場合、java.sql.SQLExceptionが出て、
    動作しなくなってしまいました。

    キャンセル

  • 2016/02/28 21:53

    申し訳ない^^;
    nabe3さんのほうが正解かも?

    キャンセル

  • 2016/02/29 00:00

    とんでもないです。
    私こそ全くわかっていないので;;
    どうもありがとうございました。

    キャンセル

0

SQLのCOUNT(*)の結果は1行なので、

/* 修正前 */
  while (rs.next()) {
   countKana = rs.getInt("countKana");
  }

↓

  /* 修正後 */
  rs.next()
  countKana = rs.getInt("countKana");


と修正して確認してみてください。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/02/29 23:20

    こちらに件数取得の3つの例が掲載されています。

    java.sql.ResultSetで取得したデータの数を得たいのですが?
    http://homepage1.nifty.com/docs/java/faq/S135.html#S135-02

    この例の2つ目のやり方が今回のやり方なのですが、
    3つ目の[rs.last();]、[rs.getRow();]が使えるなら良いですが、
    もしダメなら地道に1つ目の例のようにループして取得するしかないでしょうか・・・。
    レコード数が多いとレスポンスに問題が出そうなのでお勧めできませんが。

    もしCOUNT(*)になんらかの不具合があるのでしたら、SQLを変えて、
    SELECT sum(1) AS countKana FROM user WHERE user.initial = 'や';
    のようにして見つかったレコード数の合計数を取得して値が取れるでしょうか?

    キャンセル

  • 2016/03/01 00:26

    何度もありがとうございます。
    SQLを変えてみましたが、結果は0と返ってきました。

    もしかしたらSQLやJavaの問題ではなく、下でhirohiro様がご指摘くださった文字コードの問題かもしれないと思えてきました。
    そちらも含めて、明日になってしまいますが結果をご報告させていただきます。
    どうかよろしくお願いいたします。

    キャンセル

  • 2016/03/01 22:24

    こんばんは。

    不具合の原因は文字コードだったようです。
    数日の間おつきあいいただき、誠にありがとうございました。
    ご尽力に感謝いたします。

    キャンセル

0

while(rs.next()){
 syso("aaa");
}
と入力すると、何回aaaは出力されるでしょうか?
複数回呼ばれているようなら、rsがおかしいと思い聞いてみました。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/03/01 00:05

    ありがとうございます。

    > System.out.println(rs.getString(0));

    こちらですが、動かすと以下のSQLエラーが出ます。

    java.sql.SQLException: Column Index out of range, 0 < 1.

    添え字0は存在しない、ということでしょうか。。

    キャンセル

  • 2016/03/01 00:10

    何度もありがとうございます。
    aaaは一度だけコンソールに出力されます。

    キャンセル

  • 2016/03/01 00:44 編集

    Stringの変数に代入する際、「*」を「\\*」にしてみてもだめでしょうか?

    Stringの*と、MySQLの*とが意味が異なるため、聞いてみました。

    SELECT COUNT(*)が、SELECT COUNT(()として扱われているのではないかと。

    キャンセル

  • 2016/03/01 22:21

    不具合の原因は文字コードだったようです。
    大変お手数をおかけいたしました。
    何度もありがとうございました!

    キャンセル

0

userテーブルの各カラムの型はどうなってますか?

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/03/01 22:20

    ありがとうございます。
    カラムinitialの型は、varchar型です。
    他には、name,address,emailがありますが、こちらはvarchar型
    id,genderがint型にしています。

    不具合の原因は文字コードだったようです。
    お手数をおかけいたしました。
    ご尽力に感謝いたします。ありがとうございました。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 89.24%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る