在查询中重用SUM OVER PARTITION返回值

时间:2017-12-09 23:28:10

标签: sql postgresql

我正在寻找一种方法来保存一些计算,使其在查询中保存两次,如:

CREATE TABLE "public"."coins" (
  "id" int8 NOT NULL DEFAULT nextval('coins_id_seq'::regclass),
  "currency_symbol" text COLLATE "pg_catalog"."default" NOT NULL DEFAULT NULL,
  "currency_name" text COLLATE "pg_catalog"."default" NOT NULL DEFAULT NULL,
  "price_usd" numeric(16,7) NOT NULL DEFAULT NULL,
  "price_eur" numeric(16,7) NOT NULL DEFAULT NULL,
  "price_btc" numeric(16,7) NOT NULL DEFAULT NULL,
  CONSTRAINT "coins_pkey" PRIMARY KEY ("id")
)

CREATE TABLE "public"."market_transactions" (
  "id" int8 NOT NULL DEFAULT nextval('market_transactions_id_seq'::regclass),
  "user_id" int4 NOT NULL DEFAULT NULL,
  "quantity" numeric(18,8) NOT NULL DEFAULT NULL,
  "market_coin_id" int4 DEFAULT NULL,
  CONSTRAINT "market_transactions_pkey" PRIMARY KEY ("id")
)

我不确定分区的总和是否一直在运行。

感谢任何指针,我确信查询也可以优化,但我不确定从哪里开始。

market_transactions.market_coin_id

用户有很多涉及硬币的交易(coins.idmarket_transactions.quantity),我正在尝试对每个交易的数量(editor.setData())求和,然后将此值乘以以不同货币表示的硬币价格(英国法郎,欧元,美元)

{{3}}

2 个答案:

答案 0 :(得分:1)

在查询上运行EXPLAIN(即EXPLAIN SELECT DISTINCT ...)并查看查询计划是什么。最有可能的是,它只运行一次窗口函数。如果它多次运行,请尝试添加外部SELECT:

SELECT DISTINCT 
  price_btc, 
  price_eur, 
  price_usd, 
  currency_name,
  currency_symbol,
  holdings * price_eur AS holdings_eur,
  holdings * price_usd AS holdings_usd,
  holdings * price_btc AS holdings_btc,
  holdings
FROM (
    SELECT
    coins.price_btc,
    coins.price_eur,
    coins.price_usd,
    coins.currency_name,
    coins.currency_symbol,
    SUM ( market_transactions.quantity ) OVER ( PARTITION BY market_transactions.market_coin_id ) AS holdings 
FROM
    market_transactions
    INNER JOIN coins ON coins.id = market_transactions.market_coin_id 
WHERE
    market_transactions.user_id = 1 
) src
ORDER BY
    currency_symbol

答案 1 :(得分:1)

我建议在join之前进行汇总并执行:

SELECT c.*,
       mt.quantity * c.price_eur AS holdings_eur,
       mt.quantity * c.price_usd AS holdings_usd,
       mt.quantity * c.price_btc AS holdings_btc,
       mt.quantity * c.market_coin_id AS holdings 
FROM coins c JOIN
     (SELECT mt.market_coin_id, SUM(mt.quantity) as quantity
      FROM market_transactions t
      WHERE mt.user_id = 1 
      GROUP BY mt.market_coin_id
     ) mt
     ON c.id = mt.market_coin_id 
ORDER BY c.currency_symbol