🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
SQLite

SQLiteはリレーショナルデータベース管理システムの1つで、サーバーではなくライブラリとして使用されている。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

Q&A

解決済

3回答

66927閲覧

SELECTすると同時に件数を数えるには

退会済みユーザー

退会済みユーザー

総合スコア0

SQLite

SQLiteはリレーショナルデータベース管理システムの1つで、サーバーではなくライブラリとして使用されている。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

0グッド

1クリップ

投稿2018/04/03 06:04

初歩的な質問で恐縮なのですが、SQLの書き方です。
pythonとsqliteを使っています。

所定の条件で検索した際に、そのレコードと共に、ヒット件数を表示させたいと思っています。

sql

1select count(*) from table where age>20; 2

などとすればもちろん件数は分かるのですが、ただcountを使うと、同時にレコードをselectすることはできないように思います。

現状では

sql

1select count(*) from table where age>20; 2 3select * from table where age>20;

という具合に、2回SQLを実行しています。

これがどう見ても不細工ですし、効率も悪いように思うので、
なんとか1回のSQLで処理をしたいです。

どのようにすればよいのでしょうか。
ご指導お願いします。

気になる質問をクリップする

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

ベストアンサー

一度に取得するとしたら以下の様にすれば取得はできますが、これはこれで不細工な感じですね。

SQL

1select *,(select count(*) from table t where age>20) from table where age>20

※他にもfrom 句でインラインビューの直積などでもできますけど、不細工さは同じ

全ての行に件数が埋め込まれますので、先頭を取得した際にでも取得すればいいのですけど。
上記で行うのなら、fetchall()の結果をlen()で求める方がすっきりします。

表示する際にページ制御を行う場合は、count()を別に取得する事が多いです。
selectで全件取得はせずに、ページに表示する件数をoffset とlimitで制御して行うことになりますが、
この際のoffsetは全体の件数(=count())とページ表示件数(=limitの値)から求めます。
取得するデータの数と開始位置を指定

項目の取得と件数の取得を一度に行ってしまうと、必ず全体の取得になるので、遅くなることがあります。
※元々ページ制御を行うのは取得件数を限定して高速にしようというのが殆ど。
これはfetchall()でも同じなので、状況に応じて使い分けて下さい。

こんなのもありました。※まあ、そのような設計になっていればですけど。
OFFSETを使わない高速なページネーションの実現

投稿2018/04/03 06:36

編集2018/04/03 07:16
sazi

総合スコア25313

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2018/04/05 22:04

ありがとうございます。おっしゃるように、ページ制御の関係で利用しておりました。分けておこなうことになるのですね。補足情報もありがとうございました。
guest

0

PHPとMySQLの組み合わせのように
「SELECT * 」した際の行数を拾えるプログラムとSQLの組み合わせもあります

ただし上記参考サイトにもあるように、ほとんどのデータベースでは、
SELECT 文によって作用した行数つかむような処理はありません

SELECT COUNT(*)してからSELECT *するのは

不細工ですし、効率も悪い

ということはありません。普通の運用方法です。
逆に無理に1文にしてしまうのは、すべての行に同じ内容のデータを
表示することになり逆正規化のような考え方なのであまりおすすめできません。

投稿2018/04/04 03:29

yambejp

総合スコア116644

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2018/04/05 22:05

ありがとうございます。似たような処理を2回おこなうのはよくないのではないかとついつい思ってしまっていたのすが、普通の処理だったのですね。セオリーが分かってよかったです。
guest

0

SQL

1select count(*) as cnt, * from table where age>20;

で、count(*)の結果をカラム名cntとして同時に取れます。


**追記しました:**2018/04/03 15:58

saziさんのコメントを受けて再度確認しました。ご指摘のエラーにはなりませんでしたが、全件のデータを取れないので、回答としては間違っていて、NGですね。私の確認不足でした。申し訳ありません。(評価を下げてください)

C>sqlite3 SQLite version 3.18.0 2017-03-28 18:48:43 Enter ".help" for usage hints. Connected to a transient in-memory database. Use ".open FILENAME" to reopen on a persistent database. sqlite> CREATE TABLE t1 (age integer, name text); sqlite> INSERT INTO t1 (age, name) VALUES (5, 'name#1'); sqlite> INSERT INTO t1 (age, name) VALUES (10, 'name#2'); sqlite> INSERT INTO t1 (age, name) VALUES (20, 'name#3'); sqlite> INSERT INTO t1 (age, name) VALUES (21, 'name#4'); sqlite> INSERT INTO t1 (age, name) VALUES (35, 'name#5'); sqlite> INSERT INTO t1 (age, name) VALUES (40, 'name#5'); sqlite> sqlite> select * from t1; 5|name#1 10|name#2 20|name#3 21|name#4 35|name#5 40|name#5 sqlite> SELECT * FROM t1 WHERE age > 20; 21|name#4 35|name#5 40|name#5 sqlite> SELECT COUNT(*) AS cnt, * FROM t1 WHERE age > 20; 3|40|name#5 sqlite>

投稿2018/04/03 06:18

編集2018/04/03 07:00
dodox86

総合スコア9254

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

sazi

2018/04/03 06:36

group byが無くてもエラーにはなりませんか?
dodox86

2018/04/03 07:01

ご指摘どうもありがとうございます。エラー自体にはならないのですが結果としてはNGです。確認不足でした。
sousuke

2018/04/03 07:01

確かsqliteはガバガバなのでgruop byなくてもできますが、この場合は1行しか得られないはずです。
sazi

2018/04/03 07:02

要件的には条件の件数なので、エラーにならなければOKだと思います。 group by指定しなくてもエラーにならないのは、MySQLと同じですね。
dodox86

2018/04/03 07:02

おっしゃるとおりです。
sazi

2018/04/03 07:17 編集

あ、取得行数が変わるんですね。 暗黙的にgroup by してLSAT取得してるって感じですね。
sousuke

2018/04/03 07:05

要件は行数とデータの同時取得では?1行しか得られないとデータがないのでNGだと思います。
dodox86

2018/04/03 07:28

sousukeさん、コメントありがとうございます。要件としてNGなのも先立って補足させていただきました。RDBMSによってはGROUP BYが必要なのですね。勉強になります。
退会済みユーザー

退会済みユーザー

2018/04/05 21:59

遅くなりましたがご回答ありがとうございます。groupbyが暗黙でつくことになるのですね。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問