題目:有兩個表
表一:銷售明細
表二:產品明細
需求:查詢2020年,每月的銷售額,以及同比環比,並按照年月進行升序排序
思路:分步操作
- 獲得每月的數據
首先的抽取時間,以及獲得每個月的銷售額,要有 銷售額,兩個表肯定是要連接起來的
------- 獲取時間
YEAR(字段名)—獲取年份
MONTH(字段名)----獲取時間
SELECT YEAR(s.sail_time) 年, MONTH(s.sail_time) 月 , SUM(s.number*p.pro_price) 銷售額 FROM sail_info s LEFT JOIN produce_detail p ON s.produce_id=p.produce_id GROUP BY YEAR(s.sail_time) , MONTH(s.sail_time)
此處使用左連接的原因:是要補充銷售表里單品的價格,要以左表為基准,要用了左連接
結果:
- 單步操作獲得同比數據
同比:一般情況下是今年第n月與去年第n月比
計算方式:同比增長率=(本期數-同期數)÷同期數×100%
所以要有個本期數據與同期數據一一對應的表,那就要本期數據與同期數據分離
有了第一步之后很容易獲得數據
本期數據:
SELECT YEAR(s.sail_time) 年, MONTH(s.sail_time) 月 , SUM(s.number*p.pro_price) 銷售額 FROM sail_info s LEFT JOIN produce_detail p ON s.produce_id=p.produce_id where YEAR(s.sail_time)=2020 GROUP BY YEAR(s.sail_time) , MONTH(s.sail_time)
同期數據:
SELECT YEAR(s.sail_time) 年, MONTH(s.sail_time) 月 , SUM(s.number*p.pro_price) 銷售額 FROM sail_info s LEFT JOIN produce_detail p ON s.produce_id=p.produce_id where YEAR(s.sail_time)=2019 GROUP BY YEAR(s.sail_time) , MONTH(s.sail_time)
下面就要進行表的關聯了
本期、同期的區別就是年份不一樣,月份一樣唄,那就用月份作為連接點進行連接,代碼和結果截圖如下,同比就完成了~
計算的是本期,本期數據是關鍵所以這邊進行的是右連接—因為本期數據放在右邊,放左邊用左連接就好了
ps:如果覺得這邊跳了步驟的話可以將查詢結果改成 * 先去查看關聯之后的表
SELECT CONCAT(e,'-',a) 年月, b 月銷售額, CASE WHEN d>0 THEN CONCAT((b-d)/d*100,'%') -- 轉化為百分比,此處考慮到銷售額為0的情況,分母不能為0,用case進行了條件判斷 ELSE "同期沒有數據" END 同比 -- 這邊的文字可以 換掉 FROM (SELECT YEAR(s.sail_time) f , MONTH(s.sail_time) c , SUM(s.number*p.pro_price) d FROM sail_info s LEFT JOIN produce_detail p ON s.produce_id=p.produce_id WHERE YEAR(s.sail_time)=2019 GROUP BY MONTH(s.sail_time)) s2 RIGHT JOIN (SELECT YEAR(s.sail_time) e,MONTH(s.sail_time) a , SUM(s.number*p.pro_price) b FROM sail_info s LEFT JOIN produce_detail p ON s.produce_id=p.produce_id WHERE YEAR(s.sail_time)=2020 GROUP BY MONTH(s.sail_time)) s1 ON s1.a=s2.c
3.單步操作獲得環比數據
環比:一般是指報告期水平與前一時期水平之比,此處指本月數據與上月數據
計算方式:環比增長速度=(本期數-上期數)÷上期數×100%
肯定也是要有表的關聯了唄,怎么連呢???
既然是計算2020年的環比,那就以要計算的為基礎數據,進行表的關聯
上面已經有全部的年份、月份對應的數據,這一步主要是進行表的關聯
兩個表進行關聯:
-1 2020年數據的表,即判斷條件設置年份為2020的查詢結果表
-2 考慮到2020年一月份對應的是2019年的12月份,所以這個張表是不加判斷條件的表,包含了2019年和2020年數據的表
SELECT * FROM (SELECT YEAR(s.sail_time) e,MONTH(s.sail_time) a , SUM(s.number*p.pro_price) 本期銷售額 FROM sail_info s LEFT JOIN produce_detail p ON s.produce_id=p.produce_id WHERE YEAR(s.sail_time)=2020 GROUP BY MONTH(s.sail_time)) s1 LEFT JOIN (SELECT YEAR(s.sail_time) f, MONTH(s.sail_time) g, SUM(s.number*p.pro_price) 上期銷售額 FROM sail_info s LEFT JOIN produce_detail p ON s.produce_id=p.produce_id GROUP BY MONTH(s.sail_time),YEAR(s.sail_time)) s3 ON ((s1.a-1)=s3.g AND s1.e=s3.f) OR (s1.a=1 AND s3.g=12 AND s3.f=2019)
解析以下這個:
(s1.a-1)=s3.g AND s1.e=s3.f
這個是針對2020年2月份的數據,2020 02-06 的數據與2020 01-05的數據一一對應
按關聯前的,a(月份)和g(月份)應該是相等的,因為對比的是上一期的,所以要錯開,大的減掉等與小的
那一月份怎么辦呢??
s1.a=1 AND s3.g=12 AND s3.f=2019
這邊就不能用上面的辦法了,跨年了,所以需要用and連接的方式進行限制,而且需要限定為2019年的12月份,這邊因為數據比較少,不限定年份也沒問題
兩個部分用 or 並列存在,兩個條件要分別用括號括起來,否則這個查詢條件等於沒有。。。。
把* 換成
CONCAT(e,'-',a) 年月,f 月銷售額, CASE WHEN h>0 THEN CONCAT((b-h)/h*100,'%') ELSE "上期沒有數據" END 環比
執行查詢:
- 最后一步,將數據放到一個表里~
通過上述說明,可以發現都關聯了2020年數據查詢的表,所以可以將這個表放在中間 ,三個表進行關聯(也是操作同比數據用右連接的原因)
CASE WHEN d>0 THEN CONCAT((b-d)/d*100,'%') ELSE "同期沒有數據" END 同比 , CASE WHEN h>0 THEN CONCAT((b-h)/h*100,'%') ELSE "上期沒有數據" END 環比 FROM (SELECT MONTH(s.sail_time) c , SUM(s.number*p.pro_price) d ,YEAR(s.sail_time) ye FROM sail_info s LEFT JOIN produce_detail p ON s.produce_id=p.produce_id WHERE YEAR(s.sail_time)=2019 GROUP BY MONTH(s.sail_time)) s2 RIGHT JOIN (SELECT MONTH(s.sail_time) a , SUM(s.number*p.pro_price) b ,YEAR(s.sail_time) e FROM sail_info s LEFT JOIN produce_detail p ON s.produce_id=p.produce_id WHERE YEAR(s.sail_time)=2020 GROUP BY MONTH(s.sail_time)) s1 ON s1.a=s2.c LEFT JOIN (SELECT YEAR(s.sail_time) f, MONTH(s.sail_time) g, SUM(s.number*p.pro_price) h FROM sail_info s LEFT JOIN produce_detail p ON s.produce_id=p.produce_id GROUP BY MONTH(s.sail_time),YEAR(s.sail_time)) s3 ON ((s1.a-1)=s3.g AND s1.e=s3.f) OR (s1.a=1 AND s3.g=12 AND s3.f=2019) ORDER BY CONCAT(e,'-',a)