I am following the TypeOrm documents on how to create a ViewEntity so I can generate and query a custom view of my database. However at runtime, the SQL generated is not what I expected. The docs mention that the expression fed to @ViewEntity()
can be a query. Here is my model:
@ViewEntity({
expression: `
SELECT t1.*, t1.CountOfA + t1.CountOfB AS Total
FROM (
SELECT q.CountOfA, q.CountOfB
FROM questions q
) AS t1`
})
export class CountViewEntity {
@ViewColumn()
CountOfA: number;
@ViewColumn()
CountOfB: number;
@ViewColumn()
Total: number;
}
So I expected that the Repository<CountViewEntity>
would give me one record with CountOfA, CountOfB and Total for each row in my questions
table. So I execute this:
this.countViewRepository.find();
However the following SQL gets generated:
SELECT
CountViewEntity
.CountOfA
ASCountViewEntity_CountOfA
,CountViewEntity
.CountOfB
ASCountViewEntity_CountOfB
,CountViewEntity
.Total
ASCountViewEntity_Total
FROMcount_view_entity
CountViewEntity
And I get an error about table count_view_entity
not existing.
What am I doing wrong?
hmm... It's been a day since I put up a bounty and the answer/comment I received got me thinking: I'm a MySQL newbie as well as a TypeORM newbie so maybe I just overlooked an assumption the TypeORM docs make. I thought that the SQL generated would query actual DB tables, but I just reread the docs, in particular this part:
View entity is a class that maps to a database view
It meant nothing to me before but I've just come across something called a Database View. Maybe I should create one first and then query against that? Feeling optimistic once again...
View entity is a class that maps to a database view. You can create a view entity by defining a new class and mark it with @ViewEntity()
:
Updated as per post owner
Obviously, you must create the database views first before calling it from TypeORM
, which cause the error count_view_entity not existing
@ViewEntity()
accepts following options:
name
- view name. If not specified, then view name is generated from entity class name.database
- database name in selected DB server.schema
- schema name.expression
- view definition. Required parameter.
expression
can be string with properly escaped columns and tables, depend on database used.
Try as below
@ViewEntity({
expression: `
SELECT t1.*, t1.CountOfA + t1.CountOfB AS Total
FROM (
SELECT q.CountOfA, q.CountOfB
FROM questions q
) AS t1`
})
export class CountViewEntity {
@ViewColumn()
CountOfA: number;
@ViewColumn()
CountOfB: number;
@ViewColumn()
Total: number;
}
Do you really need Sub Query
as there is no point in selecting the same result in outer select.
@ViewEntity({
expression: `
SELECT "t1"."CountOfA" AS "CountOfA", "t1"."CountOfB" AS "CountOfB",
"t1"."CountOfA" + "t1"."CountOfB" AS "Total"
FROM "questions" "t1"
`
})
Also, you can use QueryBuilder
@ViewEntity({
expression: (connection: Connection) => connection.createQueryBuilder()
.select("t1.CountOfA", "CountOfA")
.addSelect("t1.CountOfB", "CountOfB")
.addSelect("t1.CountOfA" + "t1.CountOfB", "Total")
.from(questions, "t1")
})