I have found a solution to my problem, by using prisma.$queryRaw which I actually didn't know it existed for the few months I've been using it and only stumbled upon it now. Here's the documentation link for reference: Prisma - Raw database access

The end solution was:

await prisma.$queryRaw`SELECT * FROM FIRST JOIN SECOND ON FIRST.LPR=SECOND.LPR`

P.S. The only issue I ran into by using the queryRaw method instead of the regular Prisma Client was that the BLOB type values are retrieved as strings, instead of as a Buffer, but that can be handled both on the front-end as well as in the back-end accordingly with minor modifications to the response.

Answer from V. S. on Stack Overflow
🌐
Prisma
prisma.io › blog › prisma-orm-now-lets-you-choose-the-best-join-strategy-preview
Choosing the Best Join Strategy in Prisma ORM: join vs query
February 21, 2024 - Because "join" is the default once the preview flag is enabled, the relationLoadStrategy option could technically also be omitted in the snippet above. We show it here for illustration purposes. The difference between the two strategies is easy to see in the SQL that Prisma Client generates. We ran the query above on Prisma ORM 7.8 against a PostgreSQL database and logged the statements. With the query strategy (or without the preview flag), fetching users with their posts sends two queries, one per table:
🌐
GitHub
github.com › prisma › prisma › issues › 13517
SQL joins without relations/foreign keys/raw query · Issue #13517 · prisma/prisma
May 27, 2022 - SELECT * FROM "SmartContract" JOIN "Transaction" ON "SmartContract".address = "Transaction"."smartContractAddress" I guess one can always write raw queries, but having types + auto-generated selection fields is nice. ... kind/featureA request for a new feature.A request for a new feature.topic: prisma-clienttopic: relations
Author   prisma
Discussions

mysql - Is it possible to make a join query with Prisma without a foreign key? - Stack Overflow
I've been struggling with this for a while but with no success. I have two tables that might have a relation but not necessarily. FIRST +----+-----------+------------+ | ID | LPR | TIMESTAMP ... More on stackoverflow.com
🌐 stackoverflow.com
Missing Relationship Generation for Join Tables During Prisma DB Pull
When performing a db pull operation with Prisma to synchronize the database schema with the defined data models, it appears that the relationships involving join tables are not being generated as expected. More on github.com
🌐 github.com
5
August 14, 2023
Relations without foreign keys?
I'm very new to Prisma, so I'm not sure if I'm misunderstanding or just plain missing something, but it seems to me that using relations to define connections between models always crea... More on github.com
🌐 github.com
4
1
May 26, 2021
why are included relations not joined?
I am currently trying out Prisma and TypeORM to figure out which one to use for my data-intense web app. I really like the developer experience with Prisma, but I am now wondering why querying related tables causes multiple select statements instead of a join? More on github.com
🌐 github.com
3
12
🌐
RemixFast
remixfast.com › blog › prisma-workarounds
Prisma Workarounds - RemixFast
October 28, 2022 - It is common in a relation database ... foreign keys and show user readable labels. However, currently Prisma does not support relation/join on aggregation (group by) queries....
🌐
Hacker News
news.ycombinator.com › item
> It's true that Prisma currently doesn't do JOINs for relational queries. Inste... | Hacker News
May 15, 2025 - edit: Might as well throw in: I can't stand ORMs, I don't get why people use it, please just write the SQL · Funny relevant story: we got an OOM from a query that we used Prisma for. I looked into it - it’s was a simple select distinct. Turns out (I believe it was changed like a year ago, ...
🌐
GitHub
github.com › prisma › prisma › issues › 20679
Missing Relationship Generation for Join Tables During Prisma DB Pull · Issue #20679 · prisma/prisma
August 14, 2023 - When performing a db pull operation with Prisma to synchronize the database schema with the defined data models, it appears that the relationships involving join tables are not being generated as expected.
Author   prisma
Find elsewhere
🌐
Prisma
prisma.io › dataguide › postgresql › reading-and-querying-data › joining-tables
Joining tables in Postgres | Combine data from different tables
Joins allow you to bring together data from multiple tables by stitching together columns that contain common values. In this guide, we'll talk about the different types of joins PostgreSQL supports and how to use joins to construct more valuable queries.
🌐
GitHub
github.com › prisma › prisma › discussions › 12715
Performance: How to make prisma perform a single SQL query with joins instead of multiple queries · prisma/prisma · Discussion #12715
While it's irritating that Prisma doesn't use joins, there are two distinct issues that should be addressed separately. (1) efficiencies relating to using joins or not, and (2) data correctness relating to using joins or not.
Author   prisma
🌐
Prisma
prisma.io › home › select fields › select fields › select fields › select fields
Select fields | Prisma Documentation
If you do not pass select, include, or omit, Prisma Client returns all scalar fields for the model and excludes relations from the result.
🌐
Hacker News
news.ycombinator.com › item
I’ve tried Prisma over the last few months, but eventually decided against adopt... | Hacker News
April 8, 2019 - It supports various strategies for loading associations, including joins and bulk sideloading (pre-edge when you know what to fetch before parent entities have been loaded, and post-edge when you need parent entities before) · It is still somewhat early stage and the scope is much narrower ...
🌐
DEV Community
dev.to › edriso › prisma-relationships-finally-explained-with-mysql-side-by-side-2ap
Prisma relationships, finally explained (with MySQL side by side) - DEV Community
May 8, 2026 - Sometimes the join table really is just a connection. No savedAt, no notes, no extra columns. Just "this user is linked to that job" or "this job has these skills". In that case, the explicit SavedJob model is overkill, and Prisma offers a shorter form called implicit many-to-many. You write list fields on both models pointing at each other, with no @relation and no join model:
🌐
GitHub
github.com › prisma › prisma › issues › 5184
Use `JOIN`s in more queries · Issue #5184 · prisma/prisma
January 19, 2021 - Currently, there is no way to join tables together. Queries that include relations only include the relational data by using separate queries. I am hoping this can be implemented without a breaking API change.
Author   prisma
🌐
Prisma
prisma.io › blog › database-vs-application-demystifying-join-strategies
Database vs Application: Demystifying JOIN Strategies - Prisma
January 15, 2025 - Keep in mind we're still talking about a relatively simple scenario overall: joining three tables without additional factors most real-world applications are dealing with (e.g. filtering and pagination). When Prisma ORM was initially released in 2021, it implemented the application-level join ...
🌐
Prisma
prisma.io › home › orm › prisma schema › data model › relations › troubleshooting relations
Troubleshooting relations | Prisma Documentation
There are a couple of ways to define an m-n relationship, implicitly or explicitly. Implicitly means letting Prisma ORM handle the relation table (JOIN table) under the hood, all you have to do is define an array/list for the non scalar types on each model, see implicit many-to-many relations.
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.