如何从Knex.js中的连接表中选择特定列?

use*_*943 7 node.js knex.js

我在SQL数据库工作了大约20年,似乎无法理解Knex映射查询的方式.有人可以帮我找到正确的代码吗?

我有这个SQL查询,我想在我的nodejs应用程序中使用:

SELECT p.id, p.project_number, p.project_name, p.start_date, p.end_date,
   o.name, o.email_addr,
   c.company, c.email_addr AS company_email, c.first_name, c.last_name
FROM projects p
INNER JOIN owners o ON o.id = p.owner_id
INNER JOIN clients c ON c.id = p.client_id
Run Code Online (Sandbox Code Playgroud)

KnexJS(0.7.5)文档显示了对我的查询看起来像这样的示例:

knex.from('projects').innerJoin('owners', 'owners.id', 'projects.owner_id')
  .innerJoin('clients', 'clients.id', 'projects.client_id');
Run Code Online (Sandbox Code Playgroud)

我在文档中找不到几件事:

1)如何选择要包含的列?项目,客户和业主每个都有20到50列,我对所有这些都不感兴趣.从主表中选择列是明确的(使用select()column())但是如何从连接表中选择列?

2)有些列具有相同的名称.如何避免名称冲突(即向其他表中的列添加一些前缀)?我查看了Knex可以生成列别名(... AS ...)的方式,我不确定它是否是更复杂查询的可行选项.(即使是像上面这样的相对简单的查询)

wil*_*tgh 9

你可以试试:

knex('projects').select(['projects.id', 'projects.project_number', 'projects.project_name', 'projects.start_date', 'projects.end_date',
    'owners.name', 'owners.email_addr as owner_email_addr',
    'clients.company', 'clients.email_addr as client_email_addr', 'clients.first_name', 'clients.last_name'])
.innerJoin('owners', 'owners.id', 'projects.owner_id')
.innerJoin('clients', 'clients.id', 'projects.client_id');
Run Code Online (Sandbox Code Playgroud)

希望这可以帮助!


Moh*_*lal 7

在这个答案中,我将介绍更多内容,而不仅仅是选择和问题本身!

\n\n

选择并避免名称冲突

\n\n

选择的原则是使用select。可以通过重命名列(别名)来避免名称冲突。\n要创建别名(列重命名),只需as在列名称字符串中使用,如下面的代码片段所示:

\n\n
knex\n.select([\n    \'table_a.id\',\n    \'table_b.id as b_id\'  // --->  the way to create aliases (to avoid \n])                             //  columns overlapping and overriding\n.from(\'table_a\')\n.leftJoin(\n    \'table_b\',\n    \'table_a.table_b_id\',\n    \'table_b.id\'\n);\n
Run Code Online (Sandbox Code Playgroud)\n\n

它将生成以下 SQL:

\n\n
SELECT \n  "table_a"."id",\n  "table_b"."id" as "b_id"\nFROM \n  "table_a" \nLEFT JOIN "table_b" ON \n  "table_a"."table_b_id" = "table_b"."id"\n
Run Code Online (Sandbox Code Playgroud)\n\n

我们可以用不同的方式来表述。一些有趣的如下:

\n\n
knex(\'processes\') // <-- wihtout using from (shorter) [less sql like though]\n.select([ \n    \'processes.id as processId\',\n    \'processes.name as processName\',\n    \'processes.description as processDescription\',\n    \'processes.deleted as processDeleted\',\n    \'processes.deleteTime as processDeleteTime\',\n    \'rsp.runningSettingId\',\n    \'rsp.value as settingValue\',\n    \'rsp.startTime as settingStartTime\'\n])\n.innerJoin(\n   \'runningSettings_processes as rsp\',\n   \'processes.id\',\n   \'rsp.processId\'\n);\n
Run Code Online (Sandbox Code Playgroud)\n\n

多个连接示例(3 个及更多)

\n\n
const superJoinData = await knex( // i\'m using async await for the promises\n        knex<Process>(\'process\')//__________________________from here\n        .select([\n            \'processes.id as processId\',\n            \'processes.name as processName\', //--- conflict with rs.name\n            \'processes.description as processDescription\', //-- conflict with rs.description\n            \'processes.deleted as processDeleted\',\n            \'processes.deleteTime as processDeleteTime\',\n            \'rsp.runningSettingId\',\n            \'rsp.value as settingValue\',\n            \'rsp.startTime as settingStartTime\'\n        ])\n        .innerJoin(\n            \'runningSettings_processes as rsp\',\n            \'processes.id\',\n            \'rsp.processId\'\n        )//_______________________to here \n        .as(\'prsp\') //            |first join. (result an equivalent of a table)\n    ) // !!!!!!!!!!!!!!!!! notice how we nested a knex construct within another!!\n    .select([ // select from the resulting table of the first join !!!!\n        \'prsp.processId\',\n        \'prsp.processName\',\n        \'prsp.processDescription\',\n        \'prsp.processDeleted\',\n        \'prsp.processDeleteTime\',\n        \'prsp.runningSettingId\',\n        \'prsp.settingValue\',\n        \'prsp.settingStartTime\',\n        \'rs.name as settingName\',\n        \'rs.description as settingDescription\'\n    ])\n    .innerJoin( // ______________second inner join\n        \'runningSettings as rs\',\n        \'prsp.runningSettingId\',\n        \'rs.id\'\n    );\n
Run Code Online (Sandbox Code Playgroud)\n\n
\n

注意使用as()方法!

\n
\n\n

\xc2\xa0extra (与 select 无关,但构造和连接)

\n\n

使用 where 进行过滤:

\n\n
knex(\n  knex(\'A\').where(\'A.id\',1).as(\'t1\')\n).leftJoin(\n  knex(\'B\').where(\'B.id\', 2).as(\'t2\'), \n  \'t1.c\', \n  \'t2.d\'\n)\n\n//or filter the resulting table of the join\nknex(\'A\')\n.leftJoin(\n  knex(\'B\').where(\'B.id\', 2).as(\'t2\'), \n  \'t1.c\', \n  \'t2.d\'\n)\n.where(\'someColumn\', 2);\n
Run Code Online (Sandbox Code Playgroud)\n\n

使用回调进行进一步控制

\n\n
knex\n.select(\'*\')\n.from(function () {\n     this.select(\'*\').from(\'A\')\n     .where(\'id\',1)\n     .as(\'t1\');\n})\n.leftJoin(\n     knex(\'B\').where(\'id\',2).as(\'t2\'), \n     function () {\n          this.on(\'t1.c\', \'=\', \'t2.d\'); // <--- notice also the use of function \n     }                                        // construct for the join condition\n);\n
Run Code Online (Sandbox Code Playgroud)\n\n

与上面相同,没有函数构造(并且具有多个连接条件作为奖励)

\n\n
knex( // <--- notice the knex constructor (equivTo: knex.select().from())\n      knex(\'A\')   //NT: we already used that above when answering the question \n      .select(\'*\')\n     .where(\'id\',1)\n     .as(\'t1\'); \n)\n.leftJoin(\n     knex(\'B\').where(\'id\',2).as(\'t2\'), \n     function () { // <----- notice that in place of using the 2nd and 3d arg, we can have a function in the 2nd arg\n          this.on(\'t1.c\', \'=\', \'t2.d\').on(\'t1.s\', \'=\', \'t2.g\'); // <-----| \n     }                             // plus: multiple on conditions______/\n);\n
Run Code Online (Sandbox Code Playgroud)\n