如何根据knex.js中的第三列将一列分为两部分?

时间:2019-11-19 03:32:27

标签: postgresql knex.js

我有一个任务要弄清楚。

所以我有这个表transactions,它有2列bonustype,如:

bonus | type      
20       1
15      -1

我想要的是一个查询,其中bonus列被bonus_spent分为两列bonus_lefttype

它应该看起来像这样:

bonus_left | bonus_spent
    20            15

我知道我可以复制表并将它们与where子句连接在一起,但是有什么方法可以对单个查询执行此操作?

2 个答案:

答案 0 :(得分:2)

在普通SQL中,您将使用条件聚合。我们使用user_id列来指示奖金属于谁,并且我使用SUM进行汇总,以允许每种奖金类型中包含不止一种:

SELECT user_id,
    SUM(CASE WHEN type =  1 THEN bonus ELSE 0 END) AS bonus_left,
    SUM(CASE WHEN type = -1 THEN bonus ELSE 0 END) AS bonus_spent
FROM transactions
GROUP BY user_id

输出:

user_id     bonus_left  bonus_spent
1           20          15

Demo on dbfiddle

答案 1 :(得分:2)

我同意Nick,您应将答案标记为正确的恕我直言。为了完整性和一些Knex:

knex('users AS u')
  .join('transactions AS t', 'u.id', 't.user_id')
  .select('u.id', 'u.name')
  .sum(knex.raw('CASE WHEN t.type = 1 THEN t.bonus ELSE 0 END AS bonus_left'))
  .sum(knex.raw('CASE WHEN t.type = -1 THEN t.bonus ELSE 0 END AS bonus_spent'))

请注意,由于缺少表架构,因此未经测试。看起来大概像这样。您也可以将两个SUM作为knex.raw嵌入到选择列表中,但这可能更有条理。

请考虑将type创建为Postgres enum。这样一来,您不必记住表中的“魔术数字”,而可以编写如下比较:

CASE WHEN type = 'bonus_left'

这还可以防止您意外输入其他整数,例如99,因为Postgres将对插入进行类型检查。

我担心的是,同一张表中的奖金“左”与“花”反映了架构的一个更广泛的问题(例如,为什么总奖金不仍然是我们需要跟踪的唯一值) ?),但那可能只是我的妄想症!