在 Knex 中别名 a table

Alias a table in Knex

我有一个 SQL 查询两次引用同一个 table,我需要将 table 别名为两个单独的别名。我不太明白如何用 Knex 组合它。

有一个 'Words' table 和一个 'Users' table。单词 table 有两个外键,'author_id' 和 'winner_id',引用用户 table 的 '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 中执行此操作。我的第一次尝试不涉及别名,因此出现 'table used more than once' 错误。当我尝试使用 .as() 方法时,knex 抱怨缺少 .from() 子句。 .as() 方法是否仅用于别名子查询,我不应该期望它用于别名 tables?

Aliasing.as() 方法不仅用于子查询,还可以用于别名列名和 table。在您的情况下,您需要对 table 使用别名,因为您使用了 table 两次。在您的第一次尝试中,它出错了,因为您的 SQL 感到困惑。通过在使用两次的 table 上放置一个别名,您给它一个标识,即 ua.Users table 现在不同于 uw.Users table。希望对你有帮助。

我想我明白了。在 knex.js 中,假设您指定了一个 table,例如:

knex.select( '*' ).from( 'Users' )

然后您可以在 table 名称的引号内添加 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() 方法感到困惑,该方法(据我目前了解)仅用于子查询,而不用于别名 table 或列名。

在试图弄清楚如何 select 所有连接表中的所有列而不在列名相等的情况下相互覆盖时发现了这个问题。我就是这样做的,在每个前面加上 "tablename_":

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);

two ways 声明标识符的别名(table 或列)。可以直接为标识符提供 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"