每个UNION SELECT工作正常,但在UNION上引发错误

时间:2019-02-05 14:45:16

标签: sql mariadb union

希望有人可以通过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

UNION 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秒)才能产生其输出)

谢谢

1 个答案:

答案 0 :(得分:0)

问题可能是您的单个查询未处理整个结果集。因此,他们返回的行之前到达有问题的行。

在任何情况下,使用$arr = json_decode($GameState, true); if(array_key_exists('message', $arr)){ if($arr['message'] != 'no game for given game_id'){ echo "<h2> The Server is up and running </h2>"; }else{ echo "<h2> The Server is currently turned off </h2>"; } } 都很容易避免被零除。因此,无论您在何处进行分割,都可以使用它。例如:

nullif()