select 语句的子查询 Knex.js
Subquery of select statement with Knex.js
我正在尝试使用 Knex 创建以下带有子查询的查询:
SELECT
t.*,
(SELECT COUNT(*) FROM team_users tu WHERE TeamID = t.ID) AS UserCount,
(SELECT COUNT(*) FROM team_access ta WHERE TeamID = t.ID) AS AppCount
FROM teams t WHERE OwnerUserID = _UserID;
结果应该是团队 table 具有来自不同 table 的 UserCount 和 AppCount 的计数聚合(team_users,team_access)
id | Name | OwnerUserID | UserCount | AppCount
-----------------------------------------------------
134| Team A | 1538 | 7 | 6
135| Team B | 1538 | 4 | 2
136| Team C | 1538 | 12 | 1
我认为等效的 knex 实现是:
var subquery1 = Knex.knex('team_users').count('*').where('TeamID', 'teams.ID').as('UserCount');
var subquery2 = Knex.knex('team_access').count('*').where('TeamID', 'teams.ID').as('AppCount');
Knex.knex.select('*', subquery1, subquery2).from('teams').where("OwnerUserID", ownerId).asCallback(dataSetCallback);
运行,我确实在返回的对象中得到了 "UserCount" 和 "AppCount" 列,但始终为零,可能是因为它没有识别 'teams.ID'在子查询中。
我设法使用 Knex.raw 函数解决了它:
Knex.knex('teams')
.select('*', Knex.knex.raw('(SELECT COUNT(*) FROM team_users WHERE TeamID = teams.ID) AS UserCount'), Knex.knex.raw('(SELECT COUNT(*) FROM team_access WHERE TeamID = teams.ID) AS AppCount'))
.where("OwnerUserID", ownerId)
.asCallback(dataSetCallback);
但我很想知道如何使用子查询对象实现这一点。
您正在尝试将 teams.ID
字符串作为值传递。为了能够做到 .where('columnName', 'otherColumnName')
,必须使用 knex.ref
来传递 otherColumnName
作为标识符。
var teamsIdColumnIdentifier = knex.ref('teams.ID'); // <-- [1]
var subquery1 = Knex.knex('team_users').count('*')
.where('TeamID', teamsIdColumnIdentifier).as('UserCount');
var subquery2 = Knex.knex('team_access').count('*')
.where('TeamID', teamsIdColumnIdentifier).as('AppCount');
Knex.knex.select('*', subquery1, subquery2).from('teams')
.where("OwnerUserID", ownerId).asCallback(dataSetCallback);
[1] knex.ref
在 May 2018 中添加到 Knex 之前,您必须使用 knex.raw
,像这样;
var teamsIdColumnIdentifier = knex.raw('??', ['teams.ID']);
我正在尝试使用 Knex 创建以下带有子查询的查询:
SELECT
t.*,
(SELECT COUNT(*) FROM team_users tu WHERE TeamID = t.ID) AS UserCount,
(SELECT COUNT(*) FROM team_access ta WHERE TeamID = t.ID) AS AppCount
FROM teams t WHERE OwnerUserID = _UserID;
结果应该是团队 table 具有来自不同 table 的 UserCount 和 AppCount 的计数聚合(team_users,team_access)
id | Name | OwnerUserID | UserCount | AppCount
-----------------------------------------------------
134| Team A | 1538 | 7 | 6
135| Team B | 1538 | 4 | 2
136| Team C | 1538 | 12 | 1
我认为等效的 knex 实现是:
var subquery1 = Knex.knex('team_users').count('*').where('TeamID', 'teams.ID').as('UserCount');
var subquery2 = Knex.knex('team_access').count('*').where('TeamID', 'teams.ID').as('AppCount');
Knex.knex.select('*', subquery1, subquery2).from('teams').where("OwnerUserID", ownerId).asCallback(dataSetCallback);
运行,我确实在返回的对象中得到了 "UserCount" 和 "AppCount" 列,但始终为零,可能是因为它没有识别 'teams.ID'在子查询中。
我设法使用 Knex.raw 函数解决了它:
Knex.knex('teams')
.select('*', Knex.knex.raw('(SELECT COUNT(*) FROM team_users WHERE TeamID = teams.ID) AS UserCount'), Knex.knex.raw('(SELECT COUNT(*) FROM team_access WHERE TeamID = teams.ID) AS AppCount'))
.where("OwnerUserID", ownerId)
.asCallback(dataSetCallback);
但我很想知道如何使用子查询对象实现这一点。
您正在尝试将 teams.ID
字符串作为值传递。为了能够做到 .where('columnName', 'otherColumnName')
,必须使用 knex.ref
来传递 otherColumnName
作为标识符。
var teamsIdColumnIdentifier = knex.ref('teams.ID'); // <-- [1]
var subquery1 = Knex.knex('team_users').count('*')
.where('TeamID', teamsIdColumnIdentifier).as('UserCount');
var subquery2 = Knex.knex('team_access').count('*')
.where('TeamID', teamsIdColumnIdentifier).as('AppCount');
Knex.knex.select('*', subquery1, subquery2).from('teams')
.where("OwnerUserID", ownerId).asCallback(dataSetCallback);
[1] knex.ref
在 May 2018 中添加到 Knex 之前,您必须使用 knex.raw
,像这样;
var teamsIdColumnIdentifier = knex.raw('??', ['teams.ID']);