はじめに
ECサイトの管理者ダッシュボードに売上集計(総売上・総注文数・ステータス別集計)を表示したいとき、Prismaの集計メソッドが便利です。この記事では aggregate と groupBy の使い分けと実装例をまとめます。
この記事の対象読者・前提条件
対象読者
- Prismaで基本的なCRUDはできるが、集計処理はまだ使ったことがない方
- Next.jsで管理者ダッシュボードを作りたい方
前提条件
- Next.js 14以降(App Router)を使用
- Prismaセットアップ済み、Orderモデルに
totalAmount・statusがある
実装
1. aggregate — 合計・件数・平均を計算する
aggregate は _sum(合計)、_count(件数)、_avg(平均)などを一度に取得できます。
// app/admin/page.tsx
const salesData = await prisma.order.aggregate({
_sum: { totalAmount: true },
_count: true,
});
// salesData._sum.totalAmount → 総売上金額
// salesData._count → 総注文数
解説: SQLの SUM() や COUNT() と同じですが、Prismaだと型安全に書けます。Server ComponentなのでPrismaを直接呼び出せます。
2. groupBy — ステータス別に集計する
groupBy で特定のフィールドごとにグループ化して集計できます。
const ordersByStatus = await prisma.order.groupBy({
by: ["status"],
_count: true,
});
// 結果例:
// [
// { status: "pending", _count: 5 },
// { status: "paid", _count: 12 },
// { status: "shipped", _count: 3 },
// ]
解説: SQLの GROUP BY status と同じです。by にグループ化したいフィールドを配列で指定します。
3. ダッシュボードに表示する
// app/admin/page.tsx
export default async function AdminDashboard() {
const salesData = await prisma.order.aggregate({
_sum: { totalAmount: true },
_count: true,
});
const ordersByStatus = await prisma.order.groupBy({
by: ["status"],
_count: true,
});
return (
<>
<h1>管理者ダッシュボード</h1>
<p>総売上: ¥{salesData._sum.totalAmount?.toLocaleString()}</p>
<p>総注文数: {salesData._count}件</p>
<h2>ステータス別</h2>
{ordersByStatus.map((item) => (
<p key={item.status}>{item.status}: {item._count}件</p>
))}
</>
);
}
解説: admin/layout.tsx で認証・権限チェック済みなので、page.tsx では認証処理は不要です。
まとめ
-
aggregateは全体の合計・件数・平均を取得したいときに使う -
groupByは特定のフィールドごとに分けて集計したいときに使う - Server Component では Prisma を直接呼び出せるので、API Route を経由する必要がない