2017-12-27 918 views
0

在我的表中的數據是這樣的:司 - SQL

date, app, country, sales 
2017-01-01,XYZ,US,10000 
2017-01-01,XYZ,GB,2000 
2017-01-02,XYZ,US,30000 
2017-01-02,XYZ,GB,1000 

我需要找到,對於每個應用程序每天的基礎上,美國銷售的國標銷售的比例,因此,最好結果是這樣的:

date, app, ratio 
2017-01-01,XYZ,10000/2000 = 5 
2017-01-02,XYZ,30000/1000 = 30 

我目前傾倒一切都變成CSV和在Python離線做我的計算,但我想一切都移動到SQL側。一個辦法是給每個國家聚集成一個子查詢,加入和再劃分,如

select d1_us.date, d1_us.app, d1_us.sales/d1_gb.sales from 
(select date, app, sales from table where date between '2017-01-01' and '2017-01-10' and country = 'US') as d1_us 
join 
(select date, app, sales from table where date between '2017-01-01' and '2017-01-10' and country = 'GB') as d1_gb 
on d1_us.app = d1_gb.app and d1_us.date = d1_gb.date 

有一個不太混亂的方式去這樣做呢?

回答

5

您可以在查詢中使用SUM(CASE WHEN)和GROUP BY的比例來執行此操作,而無需子查詢。

SELECT DATE, 
     APP, 
     SUM(CASE WHEN COUNTRY = 'US' THEN SALES ELSE 0 END)/
     SUM(CASE WHEN COUNTRY = 'GB' THEN SALES END) AS RATIO  
FROM TABLE1 
GROUP BY DATE, APP; 

依據GB銷售額爲零的可能性,你可以調整GB的ELSE條件,也許ELSE 1,零錯誤,避免鴻溝。這實際上取決於你想如何處理異常。

+0

不要你所需要的'ELSE 0'對第二種情況? –

+3

@JuanCarlosOropeza。 。 。一點也不。這個表述就是你如何避免被零除。 –

+1

如果沒有最終將整個表達式評估爲NULL的GB數據,則當前公式將分母評估爲NULL。沒有拋出零分的錯誤。 – Vashi

0

您可以使用分組一個查詢,一旦提供了條件:

SELECT date, app, 
     SUM(CASE WHEN country = 'US' THEN SALES ELSE 0 END)/
     SUM(CASE WHEN country = 'GB' THEN SALES END) AS ratio 
WHERE date between '2017-01-01' AND '2017-01-10' 
FROM your_table 
GROUP BY date, app; 

然而,這給你零,如果有美國沒有記錄和NULL如果對於國標中沒有記錄。如果您需要爲這些情況返回不同的值,則可以在該部門周圍使用另一個CASE WHEN。例如,返回-1和-2分別,你可以使用:

SELECT date, app, 
     CASE WHEN COUNT(CASE WHEN country = 'US' THEN 1 ELSE 0 END) = 0 THEN -1 
      WHEN COUNT(CASE WHEN country = 'GB' THEN 1 ELSE 0 END) = 0 THEN -2 
      ELSE SUM(CASE WHEN country = 'US' THEN SALES ELSE 0 END)/
       SUM(CASE WHEN country = 'GB' THEN SALES END) 
      END AS ratio 
WHERE date between '2017-01-01' AND '2017-01-10' 
FROM your_table 
GROUP BY date, app; 
0
DROP TABLE IF EXISTS t; 
CREATE TABLE t (
    date DATE, 
    app VARCHAR(5), 
    country VARCHAR(5), 
    sales DECIMAL(10,2) 
); 

INSERT INTO t VALUES 
    ('2017-01-01','XYZ','US',10000), 
    ('2017-01-01','XYZ','GB',2000), 
    ('2017-01-02','XYZ','US',30000), 
    ('2017-01-02','XYZ','GB',1000); 


WITH q AS (
    SELECT 
     date, 
     app, 
     country, 
     SUM(sales) AS sales 
    FROM t 
    GROUP BY date, app, country 
) SELECT 
    q1.date, 
    q1.app, 
    q1.country || ' vs ' || NVL(q2.country,'-') AS ratio_between, 
    CASE WHEN q2.sales IS NULL OR q2.sales = 0 THEN 0 ELSE ROUND(q1.sales/q2.sales, 2) END AS ratio 
    FROM q AS q1 
    LEFT JOIN q AS q2 ON q2.date = q1.date AND 
        q2.app = q1.app AND 
        q2.country != q1.country 
    -- WHERE q1.country = 'US' 
    ORDER BY q1.date; 

結果對任何國家VS任何國家(WHERE q1.country = '美國' 被註釋掉)

date,app,ratio_between,ratio 
2017-01-01,XYZ,GB vs US,0.20 
2017-01-01,XYZ,US vs GB,5.00 
2017-01-02,XYZ,GB vs US,0.03 
2017-01-02,XYZ,US vs GB,30.00 

結果美國VS任何其他國家(WHERE q1.country = 'US' 未註釋)

date,app,ratio_between,ratio 
2017-01-01,XYZ,US vs GB,5.00 
2017-01-02,XYZ,US vs GB,30.00 

訣竅在JOIN子句中。 按日期,應用程序和國家/地區彙總數據的子查詢q的結果與結果本身結合,但與日期和應用程序結合在一起。

這樣,對於每個日期,應用和國家,我們都會在同一日期和應用中與任何其他國家/地區「匹配」。通過添加q1.country!= q2.country,我們排除同一個國家的結果,與*下方突出

date,app,country,sales,date,app,country,sales 
*2017-01-01,XYZ,GB,2000.00,2017-01-01,XYZ,GB,2000.00* 
2017-01-01,XYZ,GB,2000.00,2017-01-01,XYZ,US,10000.00 
2017-01-01,XYZ,US,10000.00,2017-01-01,XYZ,GB,2000.00 
*2017-01-01,XYZ,US,10000.00,2017-01-01,XYZ,US,10000.00* 
2017-01-02,XYZ,GB,1000.00,2017-01-02,XYZ,US,30000.00 
*2017-01-02,XYZ,GB,1000.00,2017-01-02,XYZ,GB,1000.00* 
*2017-01-02,XYZ,US,30000.00,2017-01-02,XYZ,US,30000.00* 
2017-01-02,XYZ,US,30000.00,2017-01-02,XYZ,GB,1000.00