00
:
00
:
00
:
00
Corso SEO AI - Usa SEOEMAIL al checkout per il 30% di sconto

Aggregazioni

Aggregazioni con Prisma

Prisma supporta operazioni di aggregazione direttamente nel client, senza dover scrivere SQL raw.

aggregate()

Il metodo aggregate() permette di calcolare valori aggregati su un modello.

_count

// Contare tutti gli utenti
const totalUsers = await prisma.user.count()

// Contare con filtri
const activeUsers = await prisma.user.count({
  where: { isActive: true },
})

// Contare campi non-null specifici
const result = await prisma.user.aggregate({
  _count: {
    _all: true,    // Totale record
    email: true,   // Record con email non-null
    bio: true,     // Record con bio non-null
  },
})
// result._count._all => 100
// result._count.bio => 45

_sum, _avg, _min, _max

const orderStats = await prisma.order.aggregate({
  _sum: {
    total: true,
    quantity: true,
  },
  _avg: {
    total: true,
  },
  _min: {
    total: true,
    createdAt: true,
  },
  _max: {
    total: true,
    createdAt: true,
  },
})

console.log('Totale vendite:', orderStats._sum.total)
console.log('Media ordine:', orderStats._avg.total)
console.log('Ordine minimo:', orderStats._min.total)
console.log('Ordine massimo:', orderStats._max.total)
console.log('Primo ordine:', orderStats._min.createdAt)

Aggregazioni con Filtri

// Statistiche solo per ordini completati dell'ultimo mese
const monthlyStats = await prisma.order.aggregate({
  where: {
    status: 'DELIVERED',
    createdAt: {
      gte: new Date('2026-01-01'),
    },
  },
  _sum: { total: true },
  _avg: { total: true },
  _count: { _all: true },
})

groupBy()

Raggruppa i risultati per uno o piu’ campi e applica aggregazioni a ciascun gruppo.

Raggruppamento Base

// Contare utenti per ruolo
const usersByRole = await prisma.user.groupBy({
  by: ['role'],
  _count: {
    _all: true,
  },
})
// [
//   { role: 'USER', _count: { _all: 80 } },
//   { role: 'ADMIN', _count: { _all: 5 } },
//   { role: 'MODERATOR', _count: { _all: 15 } },
// ]

Raggruppamento con Aggregazioni

// Vendite per categoria
const salesByCategory = await prisma.order.groupBy({
  by: ['category'],
  _sum: {
    total: true,
  },
  _avg: {
    total: true,
  },
  _count: {
    _all: true,
  },
  orderBy: {
    _sum: {
      total: 'desc',
    },
  },
})

Raggruppamento Multiplo

// Raggruppare per citta' e ruolo
const groupedUsers = await prisma.user.groupBy({
  by: ['city', 'role'],
  _count: {
    _all: true,
  },
  orderBy: {
    _count: {
      _all: 'desc',
    },
  },
})

having

Filtra i gruppi dopo l’aggregazione (equivalente SQL di HAVING):

// Citta' con piu' di 10 utenti
const popularCities = await prisma.user.groupBy({
  by: ['city'],
  _count: {
    _all: true,
  },
  having: {
    _all: {
      _count: {
        gt: 10,
      },
    },
  },
})

// Categorie con vendite totali superiori a 1000
const topCategories = await prisma.order.groupBy({
  by: ['category'],
  _sum: {
    total: true,
  },
  having: {
    total: {
      _sum: {
        gt: 1000,
      },
    },
  },
})

Filtri where e having Insieme

// where filtra PRIMA del raggruppamento
// having filtra DOPO il raggruppamento
const result = await prisma.order.groupBy({
  by: ['category'],
  where: {
    status: 'DELIVERED',           // Solo ordini consegnati
    createdAt: { gte: new Date('2026-01-01') },
  },
  _sum: { total: true },
  _count: { _all: true },
  having: {
    total: {
      _sum: { gte: 500 },         // Solo categorie con totale >= 500
    },
  },
  orderBy: {
    _sum: { total: 'desc' },
  },
})

Conteggio nelle Relazioni

Puoi includere il conteggio delle relazioni direttamente nelle query:

const usersWithCounts = await prisma.user.findMany({
  include: {
    _count: {
      select: {
        posts: true,
        comments: true,
        followers: true,
      },
    },
  },
})

// Accedere ai conteggi
usersWithCounts.forEach((user) => {
  console.log(`${user.name}: ${user._count.posts} post, ${user._count.comments} commenti`)
})

// Filtrare per conteggio di relazione
const prolificAuthors = await prisma.user.findMany({
  where: {
    posts: {
      some: {},
    },
  },
  include: {
    _count: { select: { posts: true } },
  },
  orderBy: {
    posts: { _count: 'desc' },
  },
  take: 10,
})