2017-07-19 69 views
0

我有一個名爲b_balance返回以下記錄視圖:總和結果是Oracle乘以行數

SECURITIES_CODE BUY_SELL_FLAG C_BALANCE P_BALANCE 
--------------- ------------- --------- --------- 
10042    BUY     200   0 
10042    BUY     500   0 
10042    SELL     200   0 
10042    BUY      0  5000 
10042    SELL     0  2500 
10043    BUY     300   0 
10043    SELL     0  2500 

並命名爲t_balance返回以下記錄另一個視圖:

SECURITIES_CODE BUY_SELL_FLAG C_BALANCE P_BALANCE 
--------------- ------------- --------- --------- 
10042    BUY      0  5000 
10043    BUY     300   0 
10042    SELL     200   0 
10042    SELL     0  2500 
10043    SELL     0  2500 
10042    BUY     200   0 
10042    BUY     500   0 

現在出現的問題,當我執行我的SQL

SELECT TO_CHAR(to_date('20170801','yyyyMMdd'), 'MM/dd/yyyy') AS TRADE_DATE, 
    b.securities_code           AS SECURITIES_CODE, 
    b.buy_sell_flag           AS SIDE, 
    SUM(NVL(t.c_balance,0))         AS C_t_balance, 
    SUM(NVL(b.c_balance,0))         AS C_b_balance, 
    SUM(NVL(t.c_balance,0)) - SUM(NVL(b.c_balance,0))  AS C_DIFFERENCE, 
    SUM(NVL(t.p_balance,0))         AS P_t_balance, 
    SUM(NVL(b.p_balance,0))         AS P_b_balance, 
    SUM(NVL(t.p_balance,0)) - SUM(NVL(b.p_balance,0))  AS P_DIFFERENCE 
FROM b_balance b 
FULL OUTER JOIN t_balance t 
ON b.securities_code = t.securities_code 
AND b.buy_sell_flag = t.buy_sell_flag 
GROUP BY b.securities_code, 
    b.buy_sell_flag 
ORDER BY SECURITIES_CODE, 
    SIDE ; 

此返回以下記錄:

TRADE_DATE SECURITIES_CODE SIDE C_T_BALANCE C_B_BALANCE C_DIFFERENCE P_T_BALANCE P_B_BALANCE P_DIFFERENCE 
---------- --------------- ---- ----------- ----------- ------------ ----------- ------------ ------------ 
08/01/2017 10042    BUY   2100   2100    0   15000   15000    0 
08/01/2017 10042    SELL   400   400    0   5000   5000    0 
08/01/2017 10043    BUY   300   300    0    0    0    0 
08/01/2017 10043    SELL    0    0    0   2500   2500    0 

這意味着結果被乘以行數。 我檢查堆棧溢出,並沒有發現任何錯誤根據this答案。

那麼我的SQL有什麼問題?

+0

根據所使用的連接謂詞中,之間的關係是'M:M'所以總結之前平衡得到重複。 –

+0

逐列均來自b_balance表,並與分組BY BY.securities_code,b.buy_sell_flag結果是正確的,你看這個:10043購買C_T_BALANCE - > 600?然後在分組 – tomcater

+1

之前使用聯合(而不是聯接),並根據此鏈接使用COALESCE而不是NVL更有利於性能。 https://stackoverflow.com/questions/950084/ – tomcater

回答

1

你應該加入彙總結果

SELECT TO_CHAR(to_date('20170801','yyyyMMdd'), 'MM/dd/yyyy') AS TRADE_DATE, 
    t1.SECURITIES_CODE, 
    t1.SIDE, 
    t1.C_b_balance, 
    t1.P_b_balance, 
    t2.C_t_balance, 
    t2.P_t_balance, 
from (
    SELECT 
     b.securities_code   AS SECURITIES_CODE, 
     b.buy_sell_flag    AS SIDE, 
     SUM(NVL(b.c_balance,0))  AS C_b_balance, 
     SUM(NVL(b.p_balance,0))  AS P_b_balance, 
    FROM b_balance b 
    GROUP BY b.securities_code, b.buy_sell_flag) t1 
left join (
    SELECT 
     t.securities_code   AS SECURITIES_CODE, 
     t.buy_sell_flag    AS SIDE, 
     SUM(NVL(t.c_balance,0))  AS C_t_balance, 
     SSUM(NVL(t.p_balance,0))  AS P_t_balance, 
    FROM t_balance t 
    GROUP BY t.securities_code, t.buy_sell_flag 
) on t1.securities_code = t2.securities_code and t1.buy_sell_flag = t2.buy_sell_flag 
+1

很好的答案。但是,似乎數據可能在任一表中都丟失,所以OP選擇了「完全外部連接」。我沒有理由將其改爲僅僅是「左外連接」。還有一點:有一個錯字'SSUM'。你有兩個逗號太多('AS P_b_balance,'和'AS P_t_balance,')。您缺少第二個派生表的t2限定符。 'NVL'屬於主選擇條款;在子查詢中不太可能得到一個空值,但由於外連接,可能會得到一個空值。 –

+0

不需要將字符串文字轉換爲日期;您可以使用日期字面值代替:'to_char(日期'2017-008-01','mm/dd/yyyy')'。當你不需要它們時,你使用了好的表別名'b'和't'。在你的主查詢中,你正在使用非助記別名't1'和't2'。在這裏使用更好的名字'b'和't'會更好。 –

0

當與來自不同表的聚集工作,聚集在加入之前(未聚合的加盟值):

select 
    date '2017-08-01'         as trade_date, 
    securities_code         as securities_code, 
    buy_sell_flag          as side, 
    nvl(t.sum_c_balance, 0)       as c_t_balance, 
    nvl(b.sum_c_balance, 0)       as c_b_balance, 
    nvl(t.sum_c_balance, 0) - nvl(b.sum_c_balance, 0) as c_difference, 
    nvl(t.sum_p_balance, 0)       as p_t_balance, 
    nvl(b.sum_p_balance, 0)       as p_b_balance, 
    nvl(t.sum_p_balance, 0) - nvl(b.sum_c_balance, 0) as p_difference 
from 
(
    select 
    securities_code, 
    buy_sell_flag, 
    sum(c_balance) as sum_c_balance, 
    sum(p_balance) as sum_p_balance 
    from b_balance 
    group by securities_code, buy_sell_flag 
) b 
full outer join 
(
    select 
    securities_code, 
    buy_sell_flag, 
    sum(c_balance) as sum_c_balance, 
    sum(p_balance) as sum_p_balance 
    from t_balance 
    group by securities_code, buy_sell_flag 
) t using (securities_code, buy_sell_flag) 
order by securities_code, buy_sell_flag; 
+0

哎呀,我剛剛注意到這與一個小時前scaisEdge已經給出的答案相同。抱歉。 –