繁体   English   中英

如何使用连接函数将 SQL 查询转换为 KnexJS 函数

[英]How to tranform a SQL query to a KnexJS function with a joining function

我正在尝试将 PSQL 中的以下查询转换为 KnexJS

SELECT
    sum("current")
FROM (
    SELECT
        "study_id",
        "site_id",
        "status",
        max("day") AS "day"
    FROM
        "candidates"
    WHERE
        "study_id" in('TBX1')
        AND "status" in('INCOMPLETE')
    GROUP BY
        "study_id",
        "site_id",
        "status") AS "latest"
    INNER JOIN "candidates" ON "latest"."day" = "candidates"."day"
        AND "latest"."study_id" = "candidates"."study_id"
        AND ("latest"."site_id" = "candidates"."site_id" or 
            ("latest"."site_id" is null and "candidates"."site_id" is null))
        AND "latest"."status" = "candidates"."status";

直到这一点我才能得到,但我错过了与 NULL 比较的查询部分,我不知道如何将它添加到我的 Knex 函数中

const group = [columns.studyId, columns.siteId, columns.status];
    const filterFn = this.filter;
    const x = this.tx
      .sum(selectColumn)
      .from(function subQuery() {
        this.select(group).max(columns.day, { as: 'day' }).from(tableName).groupBy(group).as('latest');
        filterFn.call({ builder: this }, filter);
      })
      .join(tableName, function joinOn() {
        [columns.day, ...group].map(column =>
          this.on(`latest.${column}`, `${tableName}.${column}`).on(
            this.tx.raw(`("latest"."site_id" = "candidates"."site_id" or
           ("latest"."site_id" is null and "candidates"."site_id" is null))`)
          )
        );
      })

join 方法正在创建我的连接,但没有 NULL 比较,我错过了原始查询中的这部分

 AND ("latest"."site_id" = "candidates"."site_id" or 
     ("latest"."site_id" is null and "candidates"."site_id" is null))

无法理解如何添加最后一部分来完成我的查询功能

棘手的一点看起来是因为您只想要site_id列的连接的null部分,但目前它包含在map函数调用中,因此每次循环都会应用。 处理它的一种方法是为site_id所需的特殊情况添加if语句。 IE

const group = [columns.studyId, columns.siteId, columns.status];
    const filterFn = this.filter;
    const x = this.tx
      .sum(selectColumn)
      .from(function subQuery() {
        this.select(group).max(columns.day, { as: 'day' }).from(tableName).groupBy(group).as('latest');
        filterFn.call({ builder: this }, filter);
      })
      .join(tableName, function () {
        [columns.day, ...group].map(column => {
            if (column === 'site_id') {
                this.on(function () {
                    this.on(`latest.${column}`, `${tableName}.${column}`)
                        .orOn(function () {
                            this.onNull(`latest.${column}`)
                                .onNull(`${tableName}.${column}`);
                        });
                });
            } else {
                this.on(`latest.${column}`, `${tableName}.${column}`);
            }
        });
    })

我无法完全重新创建您的案例,因为我无权访问您的filterFn 但是没有那个我从上面使用console.log(x.toString())得到的 sql 最终是

select sum(`current`) 
from (
    select 
        `study_id`, 
        `site_id`, 
        `status`, 
        max(`day`) as `day` 
    from 
        `candidates` 
    group by `study_id`, 
    `site_id`, 
    `status`) as `latest` 
    inner join `candidates` on `latest`.`day` = `candidates`.`day` 
    and `latest`.`study_id` = `candidates`.`study_id` 
    and (`latest`.`site_id` = `candidates`.`site_id` or 
        (`latest`.`site_id` is null and `candidates`.`site_id` is null)) 
    and `latest`.`status` = `candidates`.`status`

看起来像您所追求的(假设您的filterFn添加了所需的where子句)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM