如何计算另一个表中的指定行

时间:2019-04-28 17:50:36

标签: sql node.js knex.js

我正在使用Knex.js,并希望计算bans表中的特定行。有一个users表,其中设置了两个IP地址。 current_ipremote_ip,其中current_ip也已在bans表中设置。

现在,我想首先吸引remote_ip的用户,然后计算来自所选用户的banscurrent_ip的行。 expiration中的bans必须高于当前时间戳。

我已经用LEFT JOIN进行过尝试,这在Knex.js中有点令人困惑。

this.knex("bans").leftJoin(this.knex("users").where("remote_ip", ip)).where("expiration", ">", utils.getTime().count()

假设bans中有一行,其中current_ip位于当前时间戳上方127.0.0.1expiration,而users中则位于{{1} }也是current_ip127.0.0.1remote_ip。现在,我想按127.0.0.2吸引用户,并使用所选用户中给出的remote_ip来计数current_ip中的行。

我希望有人可以帮助我,甚至可以在Knex中建立查询。

1 个答案:

答案 0 :(得分:0)

我将逐步完成这两个步骤,然后在底部有一个组合的(一个)解决方案。

  

现在我想通过remote_ip吸引用户...

看起来您确实想要获取current_ip,但是如果您愿意,也可以轻松地将用户添加到其中。 SQL是:

 SELECT current_ip FROM users WHERE remote_ip = input_remote_ip

KNEX可以是:

function getRemoteIpUsers(input_remote_ip) {
  return knex("users")
    .select("current_ip")
    .where("remote_ip", input_remote_ip)
} 
// returns array of user records

我假设在您的用户表中,该用户是唯一的,并且您的current_ip和remote_up可以为多个用户使用相同的值,因此上述查询可能返回多个行,每个输入了远程ID的用户都将返回一行

此外,此查询可能多次返回相同的current_ip,每个用户一次。下面的“最后”部分中的组合查询本质上将忽略该查询。

  

...并使用所选用户中提供的current_ip来计算禁令中的行。

此部分的SQL是:

SELECT current_ip, count(*) as cnt FROM bans WHERE current_ip = input_current_ip AND expiration > get_time_count

KNEX可以是:

function countNonExpiredIpBans(input_current_ip) {
  return knex("bans")
    .count("* as cnt")
    .where("current_ip", input_current_ip)
    .andWhere("expiration", ">", utils.getTime().count() )
    .then((rec_arr) => {       // knex always returns an array of recs
       return { "current_ip": input_current_ip, 
                "cnt": rec_arr[0].cnt };  // I named the count field 'cnt'
    })
} 
// returns ip and count value;

最后,

您可以将2个函数放在一起,但是尝试一次查询可能是更好的方法。因此,变速,组合的SQL查询将是:

SELECT current_ip, count(*) as cnt FROM bans 
  WHERE expiration > get_time_count
    AND current_ip IN (SELECT current_ip FROM users WHERE users.remote_ip = input_remote_ip)
  GROUP by current_ip

在KNEX中,这变成...

function countCurrentIpBansForRemoteIp( input_remote_ip ) {
  return KNEX('bans')
    .select('current_ip')
    .count('* as cnt')
    .where("expiration", ">", utils.getTime().count())
    .whereIn('current_ip', function() {
         this.select('current_ip').from('users')
         .where("remote_ip", input_remote_ip);
    })
    .groupBy('current_ip')
}
// returns array of: { current_ip:'value', cnt: 88 }

免责声明-我没有实际的数据结构可以运行此功能,并且我对您的数据结构进行了一些假设,因此希望我已经关闭,对您有所帮助。