【发布时间】:2019-02-05 14:45:16
【问题描述】:
希望有人可以通过 2 个查询的 UNION 帮助 MariaDB 10.3 的初学者。
以下每个查询都可以正常工作,但是当我想在 UNION 中组合结果时,它会引发“除以 0”警告。
SQL 1:
WITH hv_sub AS (SELECT hv.portfolio,
hv.price_date,
SUM(hv.VALUE) AS curValue,
SUM(hv.VALUE) + IFNULL(SUM(tv.cashflow),0) AS netValue,
SUM(hv.retrn) AS portfolio_retrn
FROM holdings_VIEW_day_by_day hv
LEFT JOIN transactions_VIEW tv ON tv.tr_date = hv.price_date AND hv.portfolio = tv.portfolio AND hv.isin = tv.isin
WHERE hv.isin <> 'EU0000000000'
GROUP BY hv.portfolio, hv.price_date
ORDER BY hv.price_date),
portfolio_retrn_pct AS (SELECT hv_sub.portfolio,
hv_sub.price_date,
hv_sub.portfolio_retrn,
hv_sub.netValue / LAG(hv_sub.curValue,1) OVER (PARTITION BY hv_sub.portfolio ORDER BY hv_sub.price_date) AS portfolio_retrn_pct
FROM hv_sub)
SELECT prp.portfolio,
'Portfolio',
CAST(YEAR(prp.price_date) AS CHAR) AS yr,
CONCAT(ROUND(100*(EXP(SUM(LN(prp.portfolio_retrn_pct)))-1),1),"%") AS portfolio_twRoR,
SUM(prp.portfolio_retrn) AS portfolio_retrn,
0 AS yrEndValue
FROM portfolio_retrn_pct prp
GROUP BY prp.portfolio, YEAR(prp.price_date)
SQL 2:
WITH maxDates AS (SELECT hv.portfolio,
hv.isin,
YEAR(hv.price_date) as yr,
MAX(hv.price_date) as maxDate
FROM holdings_VIEW_day_by_day hv
GROUP BY YEAR(hv.price_date), hv.portfolio, hv.isin),
yrEndValues AS (SELECT md.*, hv.value
FROM holdings_VIEW_day_by_day hv
JOIN maxDates md ON md.portfolio = hv.portfolio AND md.isin = hv.isin AND md.maxDate = hv.price_date
GROUP BY hv.portfolio, hv.isin, YEAR(hv.price_date)
ORDER BY YEAR(hv.price_date), hv.stock_name)
SELECT hv.portfolio,
hv.stock_name,
CAST(YEAR(hv.price_date) AS CHAR) as yr,
CONCAT(ROUND(100*(EXP(SUM(LN(hv.retrn_pct)))-1),1),"%") AS twRoR,
ROUND(SUM(hv.retrn),0) AS retrn,
ROUND(yEV.value,0) AS yrEndValue
FROM holdings_VIEW_day_by_day hv
LEFT JOIN yrEndValues yEV ON hv.portfolio = yEV.portfolio AND hv.isin = yEV.isin AND YEAR(hv.price_date) = yEV.yr
GROUP BY hv.portfolio, hv.stock_name, YEAR(hv.price_date)
ORDER BY YEAR(hv.price_date), hv.portfolio, hv.stock_name, EXP(SUM(LN(hv.retrn_pct))) DESC
联合 SQL:
WITH maxDates AS (SELECT hv1.portfolio,
hv1.isin,
YEAR(hv1.price_date) as yr,
MAX(hv1.price_date) as maxDate
FROM holdings_VIEW_day_by_day hv1
GROUP BY YEAR(hv1.price_date), hv1.portfolio, hv1.isin),
yrEndValues AS (SELECT md.*, hv.value
FROM holdings_VIEW_day_by_day hv
JOIN maxDates md ON md.portfolio = hv.portfolio AND md.isin = hv.isin AND md.maxDate = hv.price_date
GROUP BY hv.portfolio, hv.isin, YEAR(hv.price_date)
ORDER BY YEAR(hv.price_date), hv.stock_name),
hv_sub AS (SELECT hv2.portfolio,
hv2.price_date,
SUM(hv2.VALUE) AS curValue,
SUM(hv2.VALUE) + IFNULL(SUM(tv.cashflow),0) AS netValue,
SUM(hv2.retrn) AS portfolio_retrn
FROM holdings_VIEW_day_by_day hv2
LEFT JOIN transactions_VIEW tv ON tv.tr_date = hv2.price_date AND hv2.portfolio = tv.portfolio AND hv2.isin = tv.isin
WHERE hv2.isin <> 'EU0000000000'
GROUP BY hv2.portfolio, hv2.price_date
ORDER BY hv2.price_date),
portfolio_retrn_pct AS (SELECT hv_sub.portfolio,
hv_sub.price_date,
hv_sub.portfolio_retrn,
hv_sub.netValue / LAG(hv_sub.curValue,1) OVER (PARTITION BY hv_sub.portfolio ORDER BY hv_sub.price_date) AS portfolio_retrn_pct
FROM hv_sub)
(SELECT hv.portfolio,
hv.stock_name,
CAST(YEAR(hv.price_date) AS CHAR) as yr,
CONCAT(ROUND(100*(EXP(SUM(LN(hv.retrn_pct)))-1),1),"%") AS twRoR,
ROUND(SUM(hv.retrn),0) AS retrn,
ROUND(yEV.value,0) AS yrEndValue
FROM holdings_VIEW_day_by_day hv
LEFT JOIN yrEndValues yEV ON hv.portfolio = yEV.portfolio AND hv.isin = yEV.isin AND YEAR(hv.price_date) = yEV.yr
GROUP BY hv.portfolio, hv.stock_name, YEAR(hv.price_date)
ORDER BY YEAR(hv.price_date), hv.portfolio, hv.stock_name, EXP(SUM(LN(hv.retrn_pct))) DESC)
UNION
(SELECT prp.portfolio,
'_Portfolio',
CAST(YEAR(prp.price_date) AS CHAR) AS yr,
CONCAT(ROUND(100*(EXP(SUM(LN(prp.portfolio_retrn_pct)))-1),1),"%") AS portfolio_twRoR,
SUM(prp.portfolio_retrn) AS portfolio_retrn,
0
FROM portfolio_retrn_pct prp
GROUP BY prp.portfolio, YEAR(prp.price_date))
ORDER BY yr, stock_name;
有人能指出我正确的方向吗?
进一步发现: 一旦我在最后删除全局 UNION SORT BY,警告就会消失。
(我也很乐意采取任何方式来优化这些查询......它看起来并不优雅,并且需要相当长的时间(15 秒)才能产生输出)
谢谢
【问题讨论】:
-
添加一些示例表数据和预期结果 - 全部作为格式化文本,而不是图像。在开始之前考虑阅读stackoverflow.com/help/mcve!
-
我记得当我在第一组中有一个 (n)varchar 列时,SQL 决定它只有 n 个字符宽,但第二组中的同一列更宽时,我遇到了不合理的错误。不记得错误了……那是很久以前的事了……但我记得那是荒谬的。对于咯咯笑...尝试将两列显式转换为已知的大宽度...在第二列 (hv.stock_name) vs '_Portfolio'
-
另外...看不出在联合之前的集合中有一个 order by 是有意义的...或任何与此相关的 with 子句。
-
尝试投射前 2 列,但不幸的是没有成功。谢谢你的建议。我知道订单,只是在我开始工作之前没有费心把它们拿出来