MongoDBの単一クエリで$groupとdistinct(重複排除)を同時に実行する方法
MongoDBでは、集計パイプライン(aggregate)の $group ステージに $addToSet 演算子を組み合わせることで、単一のクエリ内で「グループ化」と「distinct(重複値の抽出)」を同時に実行できます。本記事では、学生データを例に、その具体的な手順を解説します。
サンプルコレクションの作成
まず、insertOne() メソッドを使って、ドキュメントを格納したコレクションを作成します。
> db.demo16.insertOne({
... "StudentName" : "Chris",
... "StudentSection" : "A",
... "StudentAge" : 23,
... "StudentMarks" : 47
... }
... );
{
"acknowledged" : true,
"insertedId" : ObjectId("5e13827455d0fc6657d21f07")
}
> db.demo16.insertOne({
... "StudentName" : "Bob",
... "StudentSection" : "B",
... "StudentAge" : 21,
... "StudentMarks" : 85
... }
... );
{
"acknowledged" : true,
"insertedId" : ObjectId("5e13827555d0fc6657d21f08")
}
> db.demo16.insertOne({
... "StudentName" : "Carol",
... "StudentSection" : "A",
... "StudentAge" : 26,
... "StudentMarks" : 97
... }
... );
{
"acknowledged" : true,
"insertedId" : ObjectId("5e13827655d0fc6657d21f09")
}
上記のコレクションには、3名の学生データが登録されました。ChrisとCarolは同じセクション「A」に所属しており、この後の重複排除の動作を確認するのに適したサンプルです。
find()メソッドで全ドキュメントを確認
登録したすべてのドキュメントを表示するには、find() メソッドを使用します。
> db.demo16.find().pretty();
実行すると、以下の出力が得られます。
{
"_id" : ObjectId("5e13827455d0fc6657d21f07"),
"StudentName" : "Chris",
"StudentSection" : "A",
"StudentAge" : 23,
"StudentMarks" : 47
}
{
"_id" : ObjectId("5e13827555d0fc6657d21f08"),
"StudentName" : "Bob",
"StudentSection" : "B",
"StudentAge" : 21,
"StudentMarks" : 85
}
{
"_id" : ObjectId("5e13827655d0fc6657d21f09"),
"StudentName" : "Carol",
"StudentSection" : "A",
"StudentAge" : 26,
"StudentMarks" : 97
}
$groupと$addToSetでグループ化と重複排除を同時に実行
それでは、グループ化とdistinct操作を1つのクエリでまとめて実行してみましょう。ポイントは、_id を null に設定して全ドキュメントを1つのグループとして扱い、各フィールドに対して $addToSet(重複しない値の配列を作成)、$min(最小値)、$max(最大値)を適用することです。
> db.demo16.aggregate([{
... $group : {
... _id : null,
... StudentName : { $addToSet : "$StudentName" },
... StudentSection : { $addToSet : "$StudentSection" },
... StudentMinimumAge : { $min : "$StudentAge" },
... StudentMaximumAge : { $max : "$StudentAge" },
... StudentMinimumMarks: { $min : "$StudentMarks" },
... StudentMaximumMarks : { $max : "$StudentMarks" }
... }
... }]).pretty();
このクエリを実行すると、以下のような結果が出力されます。
{
"_id" : null,
"StudentName" : [
"Carol",
"Bob",
"Chris"
],
"StudentSection" : [
"B",
"A"
],
"StudentMinimumAge" : 21,
"StudentMaximumAge" : 26,
"StudentMinimumMarks" : 47,
"StudentMaximumMarks" : 97
}
結果のポイント
- StudentName: 重複のない学生名のリストが配列として返されます(distinct相当の動作)。
- StudentSection: ChrisとCarolが同じ「A」セクションでも、「A」「B」はそれぞれ1回だけ出力され、重複が自動的に除去されます。これが
$addToSetの働きです。 - 年齢・点数:
$minと$maxにより、全体の中から最小・最大の値がそれぞれ集計されています。
このように、$group ステージ内で複数の累積演算子($addToSet、$min、$maxなど)を組み合わせれば、SQLでいうGROUP BYとDISTINCTを別々のクエリで実行する必要はなく、MongoDBではたった1つのaggregateクエリで効率的に処理できます。
-
MySQLのCOUNT()とDISTINCTを組み合わせて重複行を除いた件数を取得する方法
はい、COUNT()とDISTINCTを組み合わせることで、重複を除外した行数だけをカウントして表示することができます。 MySQLでは、COUNT()関数単体で使用するとテーブル内のすべての行がカウントされますが、DISTINCTキーワードを組み合わせることで、一意な値を持つ行のみを集計対象にできます。データ分析やレポート作成の際に、重複データを排除した正確な件数が必要になる場面は多く、この組み合わせは非常に実用的です。 COUNT(DISTINCT ...) の基本構文 構文は以下の通りです。 SELECT COUNT(DISTINCT yourColumnName) AS anyVar
-
MySQLでIdごとに重複を除外してGROUP_CONCATするクエリの書き方
はじめにMySQLでは、テーブル内に同じIdとNameの組み合わせが重複して登録されているケースがあります。このような場合、DISTINCTで重複行を除外したうえでGROUP_CONCAT()を適用すれば、Idによって区別された一意な値だけを連結できます。本記事では、実際にテーブルを作成し、データを挿入してから、Idごとに重複を除外したGROUP_CONCATを実行するまでの手順を具体的に解説します。サンプルテーブルの作成まず、以下のCREATE TABLE文でテーブルを作成します。mysql> create table DemoTable ( Id int, Name