prisma icon indicating copy to clipboard operation
prisma copied to clipboard

count() support distinct

Open DregondRahl opened this issue 5 years ago • 22 comments

Problem

I have bumped into a few cases where I need to do a 'where' filter and get records that are 'distinct', to add pagination I need to do a count query also with a 'distinct' option on 'count()', based on the documentation and experience, I can't use distinct on a count()

export type FindManyUserArgs = {
  where?: UserWhereInput | null
  orderBy?: Enumerable<UserOrderByInput> | null
  skip?: number | null
  after?: UserWhereUniqueInput | null
  before?: UserWhereUniqueInput | null
  first?: number | null
  last?: number | null
}

Suggested solution

Can we update count() to support distinct as well? so it would accept the object similar to findMany()

export type FindManyUserArgs = {
  select?: UserSelect | null
  include?: UserInclude | null
  where?: UserWhereInput | null
  orderBy?: Enumerable<UserOrderByInput> | null
  cursor?: UserWhereUniqueInput | null
  take?: number | null
  skip?: number | null
  distinct?: Enumerable<UserDistinctFieldEnum>  
}

DregondRahl avatar Nov 11 '20 16:11 DregondRahl

I would really love to see this feature added.

chinanderm avatar Mar 08 '21 01:03 chinanderm

I am highly looking forward to it aswell.

lskuper avatar Jul 15 '21 11:07 lskuper

Would love for this to be implemented! 👍

jonasmerlin avatar Jul 15 '21 11:07 jonasmerlin

This would be great 👍

Product0wner avatar Jul 15 '21 11:07 Product0wner

Oddly, the TypeScript type for count this doesn't omit distinct - it just omits include and overwrites select, so there is no type error if you try to write something like prisma.myModel.count({ distinct: ['userId'] })

  type MyModelCountArgs = Merge<
    Omit<MyModelFindManyArgs, 'select' | 'include'> & {
      select?: MyModelCountAggregateInputType | true
    }
  >

hiddenist avatar Jul 15 '21 23:07 hiddenist

Oddly, the TypeScript type for count this doesn't omit distinct - it just omits include and overwrites select, so there is no type error if you try to write something like prisma.myModel.count({ distinct: ['userId'] })

  type MyModelCountArgs = Merge<
    Omit<MyModelFindManyArgs, 'select' | 'include'> & {
      select?: MyModelCountAggregateInputType | true
    }
  >

Yeah noticed that aswell. Although any query with distinct does fail.

lskuper avatar Jul 16 '21 06:07 lskuper

Any progress on this? I really need to count the number of unique occurrences in a column.

halvors avatar Aug 07 '21 10:08 halvors

For folks who need this, here's my workaround until it's supported:

 async function getReaderCount() {
   // couldn't figure out how to do this in one query without $queryRaw 🤷‍♂️
   type CountResult = [{count: number}]
   const [userIdCount, clientIdCount] = await Promise.all([
     prisma.$queryRaw`SELECT COUNT(DISTINCT "public"."PostRead"."userId") FROM "public"."PostRead" WHERE ("public"."PostRead"."userId") IS NOT NULL` as Promise<CountResult>,
     prisma.$queryRaw`SELECT COUNT(DISTINCT "public"."PostRead"."clientId") FROM "public"."PostRead" WHERE ("public"."PostRead"."clientId") IS NOT NULL` as Promise<CountResult>,
   ]).catch(() => [[{count: 0}], [{count: 0}]])
   return userIdCount[0].count + clientIdCount[0].count
 }

kentcdodds avatar Aug 20 '21 12:08 kentcdodds

This feature is really need it

Roberto-Calderon avatar Sep 29 '21 17:09 Roberto-Calderon

I'd like to have this implemented too.

orpheousff8 avatar Oct 13 '21 02:10 orpheousff8

While the workaround indeed...works, it would be great to have a fix on this as the documentation says that it should function correctly.

deekerno avatar Oct 26 '21 17:10 deekerno

Can you point us to the misleading documentation please @deekerno? That should of course not be the case while we wait for the feature to be implemented.

janpio avatar Nov 05 '21 13:11 janpio

Correct me if i am wrong @deekerno but the misleading documentation is here in the api reference https://www.prisma.io/docs/reference/api-reference/prisma-client-reference#count where it says that count has an option called distinct

stefanoruth avatar Nov 05 '21 14:11 stefanoruth

@janpio, @stefanoruth is correct with the location of the documentation. Thanks!

deekerno avatar Nov 05 '21 14:11 deekerno

Would be happy to use prisma I just couldn't do the DISTINCT bit here

 const countCandidatesAddedToListPromise = this.prisma.$queryRaw<
      {
        ownerId: string
        count: number
      }[]
    >(Prisma.sql`
    SELECT
      "ownerId",
      COUNT(DISTINCT "candidateId") as "count"
    FROM "CandidateListMap"
    WHERE "createdAt" BETWEEN ${timeRange.start} AND ${timeRange.end}
    GROUP BY "ownerId"
    ORDER BY count ${Prisma.raw(sortOrder)}
    `)

revmischa avatar Mar 10 '22 11:03 revmischa

Would be great to have this feature so we can remove the $queryRaw 🙌🏽

sergio-toro avatar May 12 '22 09:05 sergio-toro

Is there any progress on implementing this?

halvors avatar Jun 11 '22 13:06 halvors

Is it possible to do that in the latest version? nearly two years waiting.

shtse8 avatar Aug 05 '22 14:08 shtse8

Still not implemented, including in Prisma 4.0.0

matt-leyrat avatar Aug 18 '22 22:08 matt-leyrat

This feature is needed. Whats weird is that the documentation on Prisma is wrong it says count() supports distinct but the error returns: Unknown arg distinctin distinct for type AggregateProduct. Did you meanselect? Available args: type aggregateproduct { where?: productWhereInput orderBy?: List<productOrderByWithRelationInput> | productOrderByWithRelationInput cursor?: productWhereUniqueInput take?: Int skip?: Int }

image

Kayrim avatar Aug 26 '22 14:08 Kayrim

I guess the only way to support this feature is first to implement real distinct SQL queries (see #14765). Currently distinct is done programmatically, which I guess is not an option for count.

medihack avatar Sep 14 '22 13:09 medihack

凸pirsma凸 an expensive method

const userList = await this.prismaRead.user.groupBy({
      by: ['name'],
      where: name: {
          contains: name,
        },
    });
    
    const count =  userList.length;

OrOlEl avatar Sep 21 '22 04:09 OrOlEl

bump

jordanpurinton avatar Oct 31 '22 22:10 jordanpurinton

Hello, can we have an update regarding this feature ?

walidthebest avatar Nov 22 '22 11:11 walidthebest

Bump

adventurini avatar Nov 23 '22 20:11 adventurini

I would also need this feature. It's strange that it's allowed to use distinct in count by TypeScript but it fails at runtime. You could at least fix the types if you don't have enough resources to make this feature work.

Here's my workaround using findMany with distinct:

export async function countUniqueVotes() {
  const results = await prisma.vote.findMany({
    distinct: ['accountId'],
    select: {
      accountId: true,
    },
  });

  return results.length;
}

But I'm a little bit afraid of using it on large tables.

livthomas avatar Jan 26 '23 13:01 livthomas

Any updates?

felipeLeao18 avatar Feb 14 '23 19:02 felipeLeao18

Something?

raullunap avatar Feb 22 '23 21:02 raullunap

Sadly $queryRaw is really the only answer for this currently (and a ton of other feature request tickets). See the sample from @revmischa above for an example of how that'd work.

Prisma crew - there are a ton of features like this which you guys don't have implemented and encountering one suddenly forces you to jump back to raw queries. Is there some big catch-up project to handle them? Count distinct is hardly a niche use case and it's staggering that the framework can't support it along with many other standard operations and aggregations.

Initially I'd tried to use native Prisma functions for everything, but at this point my API is something like 95% raw queries due to how many restrictions I've hit. That's a big bummer and I wonder if it's indicative of how things will be in the future. I can't even use automated migrations due to how many features are unsupported there as well. Maybe some big disclaimers would be in order for onboarding guides about how Prisma isn't intended for anyone doing anything resembling analytics?

bsplosion avatar Feb 22 '23 21:02 bsplosion

Checking in on this and adding my support for this feature.

DrewVartanian avatar Mar 22 '23 01:03 DrewVartanian