别名Knex中的表

时间:2015-02-06 01:39:47

标签: sql left-join inner-join knex.js

我有一个SQL查询,它引用同一个表两次,我需要将表别名为两个单独的别名。我无法弄清楚如何用Knex来构建它。

有一个'单词'表格和用户'表。 Words表有两个外键,' author_id'和' winner_id',引用用户表' 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()方法是否仅用于别名子查询,我不应该期望它用于别名表吗?

4 个答案:

答案 0 :(得分:46)

我想我明白了。在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()方法的存在感到困惑,该方法(据我目前所理解)仅用于子查询,而不是用于别名表或列名。

答案 1 :(得分:8)

two ways个声明标识符(表或列)的别名。一个人可以直接给标识符加上一个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"

答案 2 :(得分:1)

在尝试弄清楚如何从所有联接表中选择所有列而又不覆盖彼此(如果列名相等)时发现了这个问题。这是我的方法,在每个方法的前面都加上了“ 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);

答案 3 :(得分:-1)

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