2017-08-02 37 views
9

我有一個columnSQL table。包含交貨訂單的date如何計算每學期的營業額

所以同一日期可以重複(在有一天我們delivred severals訂單),像這樣:

05-01-16 
05-01-16 
05-01-16 
08-01-16 
08-01-16 
14-01-16 
22-01-16 
22-01-16 
04-02-16 
05-02-16 
05-02-16 

我想,計算在each 6 months每篇文章的營業額的AVG,我更多地解釋:

From January to June ==> Turnover 1 
From Febrary to July ==> Turnover 2 
From March to August ==> Turnover 3 
From April to September ==> Turnover 4 
From May to Obtober ==> Turnover 5 
From June to November ==> Turnover 6 
From July to December ==> Turnover 7 

我已經提取的月份由請求波紋管,但我不能動態地計算(因爲我的數據應該是每個月變化)成交像上面這個例子:

select distinct extract (month from Article) as mt 
order by mt 

我試圖使用cursor,但我無法抵達最佳解決方案。

我做的請求來計算每文章每個客戶的營業額在the first 6 months(I手動做到了)如下:

select "LRU", "Client", round(sum("Montant_fac_eur")) 
from "foundry" 
where "Nature"='Repair' 
and "Client"={{w_widget3.selectedValue}} 
and "annee"='2016' 
and extract (month from "date") between '1' and '6' 


group by "LRU", "Client" 

她的結果如下:

LRU   Client round 
"article1"  4001 8859  Turnover of article1 from January to June 
"article2"  4001 94315 Turnover of article2 from January to June 
"article3"  4001 273487 Turnover of article3 from January to June 
"article4"  4001 22292 Turnover of article4 from January to June 
"article5"  4001 22292 Turnover of article5 from January to June 
"article6"  4001 42590 Turnover of article6 from January to June 
"article7"  4001 9965  Turnover of article7 from January to June 
"article8"  4001 39654 Turnover of article8 from January to June 
"article9"  4001 3883  Turnover of article9 from January to June 
"article10"  4001 41612 Turnover of article10 from January to June 

我想要做一個循環來計算每6個月的營業額,如果可能的話無需手動編寫它? 有人可以幫助我,給我一個解決方案或建議我該怎麼做? 謝謝。

+2

你能不能請張貼樣本輸入和預期的輸出? –

+0

我改變了我上面的問題。謝謝。 – vero

+0

在沒有敏感數據的情況下獲取「代工」表的模式將非常有用。例如。更改列名稱。 –

回答

6

這裏你可以查看你的問題的簡單定義和解決方案(如果我理解正確的你): http://sqlfiddle.com/#!9/48a2e1/1

CREATE TABLE foundry 
(
    lru varchar(50) NOT NULL, 
    client int NOT NULL, 
    purchase_date date, 
    price int NOT NULL 
); 

INSERT INTO foundry (lru, client, purchase_date, price) VALUES 
("article1", 4001, "01-01-16", 100), 
("article1", 4001, "01-01-17", 200), 
("article1", 4001, "01-02-16", 300), 
("article1", 4001, "01-04-16", 400), 
("article1", 4001, "01-06-16", 500), 
("article1", 4001, "01-08-16", 600), 
("article1", 4001, "01-10-16", 700), 
("article1", 4001, "01-11-16", 800), 
("article1", 4002, "01-01-16", 900), 
("article1", 4002, "01-07-16", 1000), 
("article1", 4002, "01-12-16", 1100); 

基本上我們有四列的表:LRU(文章名稱),客戶,購買日期和一些價格。

解決辦法是這樣的:

SELECT lru, client, avg(price), COUNT(*) as total_items, 
MONTHNAME(STR_TO_DATE(L, '%m')) as start_month, MONTHNAME(STR_TO_DATE(R, '%m')) as end_month FROM foundry, 
(
    SELECT 1 as L, 6 as R 
    UNION ALL 
    SELECT 2, 7 
    UNION ALL 
    SELECT 3, 8 
    UNION ALL 
    SELECT 4, 9 
    UNION ALL 
    SELECT 5, 10 
    UNION ALL 
    SELECT 6, 11 
    UNION ALL 
    SELECT 7, 12 
) months 
WHERE month(purchase_date) >= L AND month(purchase_date) <= R 
GROUP BY lru, client, L, R 

的理念是:

  1. 生成個月的所有可能的組合:1-6,2-7,...,7,12
  2. 加入生成的月份組合的源數據
  3. 使用AVG和GROUP BY

而結果:

lru  client avg(price) total_items  start_month  end_month 
article1 4001 300  5 January  June 
article1 4001 400  3 February July 
article1 4001 500  3 March August 
article1 4001 500  3 April September 
article1 4001 600  3 May  October 
article1 4001 650  4 June November 
article1 4001 700  3 July December 
article1 4002 900  1 January  June 
article1 4002 1000 1 February July 
article1 4002 1000 1 March August 
article1 4002 1000 1 April September 
article1 4002 1000 1 May  October 
article1 4002 1000 1 June November 
article1 4002 1050 2 July December 
+0

從今年下半年開始的6個月的間隔如何? 8-1(明年)? – miazo

+0

然後我們應該使用UNION ALL來增強查詢。另外,我們應該計入一年。所以我們可以生成月份和年份的可能組合。 {generated_month_combinations}加入{possible_years} –

+0

好的解答tvelkyy感謝您花時間解釋它。 – Rob212

2

我會爲每個六個月的覆蓋範圍推薦通用表格表達式。 https://technet.microsoft.com/en-us/library/ms186243(v=sql.105).aspx 喜歡: 與TP1 (Turnoverperiod,Averagevaule) 作爲 ( 選擇 'PERIOD1' 作爲Turnoverperiod, AVG(週轉)作爲Averagevalue 其中period1.startdate之間日期period2.enddate ) , TP2爲 ( .... TP2 )

SELECT * FROM TP1 工會 SELECT * FROM TP2

另外,您可以創建一個動態的sql字符串(nvarchar(max)),您可以編程方式追加聯合查詢,然後使用sp_executesql語句。

+0

「期間」,「期間1」和「期間2」是列嗎?因爲我的專欄包含了她上面例子中的結構日期,所以在這種情況下,我應該手動編寫日期。 – vero

2

我不知道你正在使用,所以這裏一個可能的解決方案與ANSI SQL(使用RDBMS模擬)

嘗試解決這個問題,在2個步驟,這RDBMS:

  1. 創建視圖在形式(可以說你怎麼稱呼它v_turnover_per_month),在你的源表使用基本組由語法:

    article month turnover 
    art1  201701 1000 
    art1  201702 1020 
    ...  ...  ... 
    art2  201701 5000 
    ...  ...  ... 
    
  2. 使用下面的select語句

    SELECT article, 
         'Turnover from ' || m1.month || ' until ' || m6.month as title, 
         max(m1.turnover + m2.turnover + m3.turnover + m4.turnover + m5.turnover + m6.turnover) as total_turnover_6month 
    
    FROM v_turnover_per_month as m6 
    JOIN v_turnover_per_month as m5 ON m6.article = m5.article and m5.month+1=m6.month 
    JOIN v_turnover_per_month as m4 ON m6.article = m4.article and m4.month+1=m5.month 
    JOIN v_turnover_per_month as m3 ON m6.article = m3.article and m3.month+1=m4.month 
    JOIN v_turnover_per_month as m2 ON m6.article = m2.article and m2.month+1=m3.month 
    JOIN v_turnover_per_month as m1 ON m6.article = m1.article and m1.month+1=m2.month 
    
    GROUP BY 1, 2; 
    
+0

OP正在使用mysql –

2

這是我的看法:

DROP TABLE IF EXISTS test; 

# credit to tvelykyy for providing some test data and table def which I adapted 
CREATE TABLE test (lru VARCHAR(16), `client` INTEGER UNSIGNED, purchase_date DATE, price int NOT NULL); 

INSERT INTO test (lru, client, purchase_date, price) VALUES 
("article1", 4001, '2016-01-01', 100), 
("article1", 4001, '2016-02-01', 200), 
("article1", 4001, '2016-03-01', 300), 
("article1", 4001, '2016-04-01', 400), 
("article1", 4001, '2016-05-01', 500), 
("article1", 4001, '2016-06-01', 600), 
("article1", 4001, '2016-07-01', 700), 
("article1", 4001, '2016-08-01', 800), 
("article1", 4002, '2016-01-01', 1100), 
("article1", 4002, '2016-06-01', 1200); 

SELECT A.lru, A.`client`, ROUND(SUM(price)) round, CONCAT('Turnover of article ', A.lru, ' from ', DATE_FORMAT(DATE_ADD(MAX(B.purchase_date), INTERVAL -6 MONTH), '%M %Y'), ' to ', DATE_FORMAT(MAX(B.purchase_date), '%M %Y')) period FROM 
    (
    SELECT DISTINCT lru, LAST_DAY(purchase_date) purchase_month, `client` FROM test 
) A 
LEFT OUTER JOIN 
    test B 
ON A.lru = B.lru AND A.`client` = B.`client` AND A.purchase_month >= LAST_DAY(B.purchase_date) AND DATE_ADD(A.purchase_month, INTERVAL -6 MONTH) < LAST_DAY(B.purchase_date) 
GROUP BY A.lru, A.`client`, A.purchase_month 
ORDER BY A.lru, A.`client`, A.purchase_month; 

查詢的工作方式是選擇DISTINCT LRU,客戶和幾個月的子查詢中,它允許一個LEFT JOIN回原來的數據ON lru,客戶和過去六個月的日期,每個月的最後一天以標準方式定義月份。最後使用指定的聚合。

如果您需要進一步的信息,請讓我知道,或者我完全不瞭解這個問題。

感謝,

詹姆斯