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

How to split one column into two separated by according to third column in knex.js?

我有一个任务一直在绞尽脑汁。

所以我有这个 table transactions 它有 2 列 bonustype 像 :

bonus | type      
20       1
15      -1

我想要的是 bonus 列的查询按 type.

分为两列 bonus_spentbonus_left

大概应该是这样的:

bonus_left | bonus_spent
    20            15

我知道我可以复制 tables 并用 where 子句连接它们,但是有什么方法可以对单个查询执行此操作吗?

在原版 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

我同意 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'))

请注意,缺少您的 table 架构,这是未经测试的。它看起来大致像这样。您也可以将两个 SUM 作为 knex.raw 嵌入 select 列表中,但这可能更有条理。

考虑将 type 创建为 Postgres enum。这将使您不必记住 table 中的 'magic number' 是什么,而是像这样编写比较:

CASE WHEN type = 'bonus_left'

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

我一直担心在同一个 table 中有奖金 'left' 与 'spent' 反映了架构的更广泛问题(例如,为什么不是总金额奖金仍然是我们需要跟踪的唯一价值?)但也许这只是我的偏执狂!