昨晚一個朋友讓我幫忙寫一條 sql, 說是有一張訂單表, 要查詢出天天有多少人下單, 有多少人付款。聽到這裏可能不少人覺得用 group by 分組, count 和 sum統計函數,問題就解決了。例如:sql
select 下單時間,count(下單時間)as 訂單數量, sum(付款金額) as 實付金額 from 訂單表 group by 下單時間
可是咱們要考慮的是,用戶有可能今天下訂單,可是到次日或者第三天才付款。這個時候這條訂單的付款數據 要算到 次日或者第三天去。有可能由於個人表達有問題,有的人沒聽懂,下面就貼出詳細過程。函數
根據他的描述,我臨時建了一張表。 固然,實際的訂單表很複雜, 爲了簡化並突出重點,我只抽出了其中幾個字段,字段名和類型也是隨便寫的。表結構以下:code
CREATE TABLE `tb_order` ( `id` varchar(32) NOT NULL DEFAULT '', -- id `status` varchar(20) DEFAULT NULL, -- 訂單狀態 `createtime` datetime DEFAULT NULL, -- 訂單建立時間 `paytime` datetime DEFAULT NULL, -- 訂單支付時間 `total` decimal(10,0) DEFAULT NULL, -- 訂單支付金額 PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1;
插入的數據要涵蓋實際生產的全部狀況,這裏總共插入了 8 條訂單數據, 下單日期爲 2019-03-11 至 2019-03-15 五天的數據。訂單類型有blog
1. 當天下單 並 當天付款的ci
2. 當天下單 但 一直未付款的date
3. 當天下單 但 次日才付款的select
INSERT INTO `tb_order` VALUES ('1', '1', '2019-03-11 21:44:18', NULL, 100); INSERT INTO `tb_order` VALUES ('2', '2', '2019-03-12 21:44:46', '2019-03-12 21:45:12', 200); INSERT INTO `tb_order` VALUES ('3', '2', '2019-03-13 21:45:27', '2019-03-13 21:45:32', 120); INSERT INTO `tb_order` VALUES ('4', '2', '2019-03-14 21:45:49', '2019-03-14 21:46:50', 50); INSERT INTO `tb_order` VALUES ('5', '1', '2019-03-15 21:46:14', NULL, 60); INSERT INTO `tb_order` VALUES ('6', '2', '2019-03-11 21:53:36', '2019-03-12 21:53:42', 100); INSERT INTO `tb_order` VALUES ('7', '2', '2019-03-15 21:56:11', '2019-03-15 21:56:15', 60); INSERT INTO `tb_order` VALUES ('8', '2', '2019-03-12 21:57:31', '2019-03-12 21:57:37', 100);
根據咱們的問題, 咱們先找出幾個關鍵字, 根據 「天天」 咱們想到了用 group by 對下單時間進行分組 ,而後咱們須要查詢出來的字段有 「下單時間」, 」下單數量「,」付款金額「。可是咱們上面說了,付款金額這個字段比較難查,咱們暫時先忽略這個字段,因而就有了下面的 sql方法
select t.createtime, count(t.createtime) as '下單數量' from tb_order t group by DATE_FORMAT(t.createtime,'%Y-%m-%d');
此時咱們的任務完成了三分之一,接下來咱們只查詢出天天訂單的 ‘實付金額’, sql 以下:im
select paytime, sum(total)as '實付金額' from tb_order group by DATE_FORMAT(paytime,'%Y-%m-%d');
到這裏,任務只能說完成了三分之二,由於咱們須要同時查出來‘ 訂單數’ 和 ‘實付金額’ 這兩個字段。既然咱們能經過對同一張表分開查的方法實現咱們的需求,那麼咱們對同一張表進行表關聯是否是就能夠同時查出兩個字段了 ?答案是 yes 。下面是完整的 sql:支付
SELECT t.createtime, COUNT(t.createtime) AS '下單數量', t1.tol AS '實付金額' FROM tb_order t LEFT JOIN ( SELECT paytime, SUM(total) AS tol FROM tb_order WHERE `status`='2' GROUP BY DATE_FORMAT(paytime,'%Y-%m-%d') ) t1 ON DATE_FORMAT(t1.paytime,'%Y-%m-%d')=DATE_FORMAT(t.createtime,'%Y-%m-%d') GROUP BY DATE_FORMAT(t.createtime,'%Y-%m-%d')
當咱們不能從同一張表同時查詢出這兩個字段,可是咱們能夠分開查的時候,能夠嘗試用關聯表,上面最終的 sql 很簡單,把咱們分析過程的 第一步 和 第二步 的 sql,用一個 left join 鏈接起來,最後加上下面的條件,就解決了當天下單,隔天付款的狀況。
ON DATE_FORMAT(t1.paytime,'%Y-%m-%d')=DATE_FORMAT(t.createtime,'%Y-%m-%d')