RTFM: https://www.prisma.io/docs/concepts/components/prisma-client/raw-database-access#tagged-template-helpers

import { Prisma } from "@prisma/client";

const ids = [1, 3, 5, 10, 20];
const result = await prisma.$queryRaw`SELECT * FROM User WHERE id IN (${Prisma.join(
  ids
)})`;
Answer from Michael Dausmann on Stack Overflow
🌐
Prisma
prisma.io › home › relation queries › relation queries › relation queries › relation queries
Relation queries (Concepts) | Prisma Documentation
const users = await prisma.user.findMany({ relationLoadStrategy: "join", // or 'query' select: { posts: true, }, });
Discussions

Type error in `IN` clause in postgreSQL using `$queryRaw` when upgrading to v4
Bug description There seems to be a regression regarding IN clauses in postgreSQL in prisma v4. The issue happened on postgresql and the behaviour changed somewhere between prisma 3.15.2 and 4.2.1. For a given table of this structure: CR... More on github.com
🌐 github.com
21
August 24, 2022
postgresql - Prisma $queryRaw with variable length parameter list - Stack Overflow
As @MichaelDausmann has mentioned above, there is a Prisma function that joins array items and formats the SQL by the types of parameters. But when you use uuid type, Prisma's join function formats the parameters adding double apostrophe. So you can take error like 'type mismatch' in PostreSQL. More on stackoverflow.com
🌐 stackoverflow.com
How to reproduce a Prisma `include` statement for arrays of related entities without SQL?
Hello, I'm trying to translate ... channels LEFT JOIN channel_performance ON channels.id = channel_performance.channel_id GROUP BY channels.id; ``` My issue is that I don't know how to use / when to use the `array_agg` - do I have to use raw SQL ? In Prisma, I could just do ... More on answeroverflow.com
🌐 answeroverflow.com
April 20, 2023
Queryraw condition joining
Each condition is constructed using Prisma.sql to safely inject parameters. The conditions array is joined with AND using Prisma.join with a string separator ' AND '. The final query is constructed using Prisma.sql, ensuring that the SQL string and the parameters are correctly aligned. More on github.com
🌐 github.com
2
2
July 23, 2024
🌐
Nico's Blog
nico.fyi › blog › prisma-join-relation
The new join relation in Prisma | Nico's Blog
March 5, 2024 - The final aggregation into JSON ... user's array. The LEFT JOIN ensures all users are returned, even those without posts, with post information included only for those who have them. It's intriguing how a task that can be succinctly described in human language ("Getting 10 users and their respective 3 posts") translates into a relatively complex SQL operation. Yet, Prisma simplifies ...
🌐
Palo Alto Networks
docs.paloaltonetworks.com › prisma › prisma-cloud › prisma-cloud-rql-reference › rql-reference › operators
Prisma Cloud Enterprise Edition
September 8, 2023 - Welcome to the documentation for Enterprise Edition, a Cloud Native Application Protection Platform (CNAPP) that protects your applications from code to cloud, reduces risks, and ...
🌐
GitHub
github.com › prisma › prisma › issues › 14978
Type error in `IN` clause in postgreSQL using `$queryRaw` when upgrading to v4 · Issue #14978 · prisma/prisma
August 24, 2022 - const rows = await this.prismaClient.$queryRaw< { id: string }[] >(Prisma.sql` SELECT id FROM repro WHERE id = ANY (ARRAY[${Prisma.join(ids)}]::uuid[]); `) I haven't seen what would cause this in the upgrade guide and it does look like a regression to me. I'm guessing there's a change in how the casting is done which broke this query.
Author   prisma
🌐
Thoughtbot
thoughtbot.com › blog › joining-postgres-tables-using-arrays-of-ids
Joining Postgres tables using arrays of IDs
January 10, 2025 - We can make a “virtual” join table using a database view, with Postgres’s unnest() function. Credit goes to the folks at Sequin for suggesting this technique for working with Airtable data. unnest(array_column) turns an array into rows, where each element of the array gets a row. Here we’ll use Prisma’s naming format for join tables.
Find elsewhere
🌐
Answer Overflow
answeroverflow.com › m › 1098587416304033972
How to reproduce a Prisma `include` statement for arrays of related entities without SQL? - Drizzle Team
April 20, 2023 - In my case the objective is to ... Thank you ! ... You can use few approaches for that 1. Just use simple select with join and then aggregate results in your code....
🌐
GitHub
github.com › prisma › prisma › discussions › 24838
Queryraw condition joining · prisma/prisma · Discussion #24838
July 23, 2024 - The conditions array is joined with AND using Prisma.join with a string separator ' AND '. The final query is constructed using Prisma.sql, ensuring that the SQL string and the parameters are correctly aligned.
Author   prisma
🌐
Answer Overflow
answeroverflow.com › m › 1258099361745866752
Can I opt into join vs every query being join by default? - Prisma
July 3, 2024 - You can opt into join for specific queries by specifying the join strategy for individual queries as needed. For example: const result = await prisma.user.findMany({ include: { posts: true, }, relationLoadStrategy: 'join', // Opt into join for this specific query });
🌐
Prisma Cloud
docs.prismacloud.io › en › enterprise-edition › content-collections › search-and-investigate › rql-operators
Prisma Cloud Technical Documentation
June 11, 2025 - You can use the following operators and conditions to compare or validate results: ... Joins allow you to get data from two different APIs where you have combined different conditions.
Top answer
1 of 2
18

Despite the accepted answer, the actual answer is: No.

For actual performant joins to work, they must solve an issue that's been open for about a year and a half as of writing this response: https://github.com/prisma/prisma/issues/5184

Currently, there is no way to join tables together. Queries that include relations only include the relational data by using separate queries.

2 of 2
16

Yes, this is possible with Prisma!. For making this work, you need to specify on your "schema.prisma" file how are models related with each other. That way, code generation will set the possible queries/operations.

Change it to this:

model Post {
  id              Int      @id @unique @default(autoincrement()) @map("id")
  userId          Int      @map("user_id")
  movieId         Int      @unique @map("movie_id")
  title           String   @map("title") @db.Text
  description     String?  @map("description") @db.Text
  tags            Json?    @map("tags")
  createdAt       DateTime @default(now()) @map("created_at") @db.DateTime(0)
  image           String?  @default("https://picsum.photos/400/600/?blur=10") @map("image") @db.VarChar(256)
  year            Int      @map("year")
  submittedBy     String   @map("submitted_by") @db.Text
  tmdbRating      Decimal? @default(0.0) @map("tmdb_rating") @db.Decimal(3, 1)
  tmdbRatingCount Int?     @default(0) @map("tmdb_rating_count")
  ratings         Rating[]

  @@map("posts")
}

model Rating {
  id        Int       @unique @default(autoincrement()) @map("id") @db.UnsignedInt
  userId    Int       @map("user_id") @db.UnsignedInt
  rating    Int       @default(0) @map("rating") @db.UnsignedTinyInt
  entryId   Int
  entry     Post      @relation(fields: [entryId], references: [id])
  createdAt DateTime  @default(now()) @map("created_a") @db.DateTime(0)
  updatedAt DateTime? @map("updated_a") @db.DateTime(0)

  @@id([entryId, userId])
  @@map("ratings")
}

Note: Please follow the naming conventions (singular form, PascalCase). I made those changes for you at the schema above. @@map allows you to set the name you use on your db tables.

Then, after generating the client, you will get access to the relational operations.

    // All posts with ratings data
    const postsWithRatings = await prisma.post.findMany({
        include: {
            // Here you can keep including data from other models
            ratings: true
        },
        // you can also "select" specific properties
    });

    // Calculate on your API
    const ratedPosts = postsWithRatings.map( post => {
        const ratingsCount = post.ratings.length;
        const ratingsTotal = post.ratings.reduce((acc, b) => acc + b.rating, 0)
        return {
            ...post,
            userRating: ratingsTotal / ratingsCount
        }
    })

    // OR...


    // Get avg from db
    const averages = await prisma.rating.groupBy({
        by: ["entryId"],
        _avg: {
            rating: true
        },
        orderBy: {
            entryId: "desc"
        }
    })
    //  Get just posts
    const posts = await prisma.post.findMany({
        orderBy: {
            id: "desc"
        }
    });
    // then match the ratings with posts
    const mappedRatings = posts.map( (post, idx) => {
        return {
            ...post,
            userRating: averages[idx]._avg.rating
        }
    })

You could also create a class with a method for making this easier. But I strongly recommend you to implement GraphQL on your API. That way, you can add a virtual field inside your post type. Any time a post is requested alone or in a list, the average will be calculated. In that same way, you would have the flexibility to request data from other models and the "JOINS" will get handled for you automatically.

Last but not least, if you ever want to do a lot of queries at the same time, you can take advantage of the Prisma transactions.

🌐
Prisma
prisma.io › home › raw queries › raw queries › raw queries › raw queries
Raw queries | Prisma Documentation
Prisma Client specifically uses SQL Template Tag, which exposes a number of helpers. For example, the following query uses join() to pass in a list of IDs:
🌐
Prisma
prisma.io › home › relations and joins › relations and joins › relations and joins › relations and joins
Relations and joins in Prisma Next | Prisma Documentation
1 week ago - "Using the prisma-next-queries skill, fetch each user with their five newest posts in one query." "Model a many-to-many between Post and Tag with an explicit junction model, and write the nested include that reads a post's tag names." "Find users that have at least one published post, using a relation predicate instead of a loop." Use advanced queries for explicit joins, flat junction traversals, and $lookup pipelines.
🌐
Prisma
prisma.io › home › working with scalar lists › working with scalar lists › working with scalar lists › working with scalar lists
Working with scalar lists/arrays (Concepts) | Prisma Documentation
const posts = await prisma.post.findMany({ where: { tags: { hasEvery: ["databases", "typescript"], }, }, }); This section applies to PostgreSQL and CockroachDB. When using scalar list filters with a relational database connector, array fields with a NULL value are not considered by the following conditions: NOT (array does not contain X) isEmpty (array is empty) This means that records you might expect to see are not returned.
🌐
Pothos-graphql
pothos-graphql.dev › docs › plugins › prisma › connections
Connections
resolve: Like the resolver for prismaField, the first argument is a query object that should be spread into your prisma query. The resolve function should return an array of nodes for the connection.
🌐
Wanago
wanago.io › home › api with nestjs #109. arrays with postgresql and prisma
API with NestJS #109. Arrays with PostgreSQL and Prisma
May 22, 2023 - With them, we can store collections of values within a single column, reducing the need to create separate tables. This can help us achieve better performance and more efficient storage. In this article, we learn how to manage arrays through raw SQL and Prisma.