我有一个SQL查询两次引用同一个表,我需要将该表别名为两个单独的别名。我不太明白如何用Knex来写这个。
有一个"Words"表和一个"Users"表。Words表有两个外键"author_id"one_answers"winner_id",它们引用了Users表的"id"列。
以下是我试图在Knex:中编写的SQL
SELECT w.*, ua.name, uw.name FROM Words AS w
INNER JOIN Users AS ua ON w.author_id = ua.id
LEFT JOIN Users AS uw ON w.winner_id = uw.id
我有点不知道如何在Knex做到这一点。我的第一次尝试不涉及别名,所以我得到了一个"表使用了一次以上"的错误。当我尝试使用.as()方法时,knex抱怨缺少.from()子句。.as()方法是否只用于别名子查询,而我不应该期望它用于别名表?
我想我想通了。在knex.js中,假设您指定了一个表,如:
knex.select( '*' ).from( 'Users' )
然后,您只需在表名的引号中添加AS关键字即可对其进行别名,如下所示:
knex.select( '*' ).from( 'Users AS u' )
您也可以对列名执行此操作;所以我最初的SQL在knex land中会是这样的:
knex.select( 'w.*', 'ua.name AS ua_name', 'uw.name AS uw_name' )
.innerJoin( 'Users AS ua', 'author_id', 'ua.id' )
.leftJoin( 'Users as uw', 'winner_id', 'uw.id' )
我想我对knex的.as()方法的存在感到困惑,据我目前所知,该方法只用于子查询,而不用于别名表或列名。
有两种方法可以为标识符(表或列)声明别名。可以直接为标识符提供as aliasName后缀(例如identifierName作为aliasName),也可以传递对象{aliasName:identifierName'}。
因此,以下代码:
knex.select('w.*', 'ua.name', 'uw.name')
.from({ w: 'Words' })
.innerJoin({ ua: 'Users' }, 'w.author_id', '=', 'ua.id')
.leftJoin({ uw: 'Users' }, 'w.winner_id', '=', 'uw.id')
.toString()
将编译为:
select "w".*, "ua"."name", "uw"."name"
from "Words" as "w"
inner join "Users" as "ua" on "w"."author_id" = "ua"."id"
left join "Users" as "uw" on "w"."winner_id" = "uw"."id"
当试图弄清楚如何在列名相等的情况下从所有联接表中选择所有列而不相互覆盖时,发现了这个问题。我就是这样做的,每个表都有"表名_":
const columnToText = (table, column) => `${table}.${column} as ${table}_${column}`;
const prepareColumns = async (table) => {
const columnsInfo = await knex(table).columnInfo();
return Object.keys(columnsInfo).map(column => columnToText(table, column));
};
const selectColumns = (await Promise.all([
'joined_table1',
'joined_table2',
'main_table',
].map(prepareColumns)))
.reduce((acc, item) => ([...acc, ...item]), []);
const data = await knex('main_table')
.leftJoin('joined_table1', 'main_table.joined_table1_id', 'joined_table1.id')
.leftJoin('joined_table2', 'main_table.joined_table1_id', 'joined_table2.id')
.select(...selectColumns);
别名或.as()
方法不仅用于子查询,还可以用于别名和表。在您的情况下,您需要使用表的别名,因为您使用了该表两次。在您的第一次尝试中,它出现了一个错误,因为您的SQL被混淆了。通过在使用了两次的表上放置一个别名,您为它提供了一个标识,即ua.Users
表现在与uw.Users
表不同。希望它能帮助你。