【Mysql】Mysql似oracle分析函式sum over的實現
先看oracle怎麼實現的
mysql的實現
結果
原資料
-
select deptno,ename,sal,sum(sal) over(order by ename) from emp; --姓名排序連續求和
-
select deptno,ename,sal,sum(sal) over(order by deptno) from emp; --所有部們排序連續求和
-
select deptno,ename,sal,sum(sal) over(partition by deptno) from emp; ---各個部門的總和
-
select deptno,ename,sal,sum(sal) over(partition by deptno order by ename) from emp; ---各個部門之間連續求和
-
select deptno,ename,sal,sum(sal) over(order by deptno,ename) from emp;
-
-
-
select deptno,ename,sal,
-
sum(sal) over (partition by deptno order by ename) 部門連續求和,--各部門的薪水"連續"求和
-
sum(sal) over (partition by deptno) 部門總和, -- 部門統計的總和,同一部門總和不變
-
100*round(sal/sum(sal) over (partition by deptno),4) "部門份額(%)",
-
sum(sal) over (order by deptno, ename) 連續求和, --所有部門的薪水"連續"求和
-
sum(sal) over () 總和, -- 此處sum(sal) over () 等同於sum(sal),所有員工的薪水總和
-
100*round(sal/sum(sal) over (),4) "總份額(%)"
- from emp
mysql的實現
- 如下:
-
SELECT a.id,a.user_id,a.borrow_id, a.repayment_money,
(SELECT SUM(repayment_money) FROM rb_repayment_period WHERE id<=a.id) "累加和", -
(SELECT AVG(repayment_money) FROM rb_repayment_period WHERE id<=a.id) "平均值" ,
(SELECT SUM(repayment_money) FROM rb_repayment_period WHERE borrow_id=a.borrow_id GROUP BY borrow_id) "每組和",
(SELECT SUM(repayment_money) FROM rb_repayment_period) "全部和",
(SELECT SUM(repayment_money) FROM rb_repayment_period WHERE id<=a.id GROUP BY borrow_id HAVING borrow_id=a.`borrow_id` ) "每組累加和"
FROM rb_repayment_period a;
結果
原資料
- sql:
-
CREATE TABLE `rb_repayment_period` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主鍵',
`borrow_id` int(11) DEFAULT '0' COMMENT '標的id',
`user_id` int(11) DEFAULT '0' COMMENT '借款人id',
`repayment_money` decimal(20,6) DEFAULT '0.000000' COMMENT '本次還款金額',
`capital_money` decimal(20,6) DEFAULT '0.000000' COMMENT '本金',
`expect_money` decimal(20,6) DEFAULT '0.000000' COMMENT '預期收益',
`exceed_money` decimal(20,6) DEFAULT '0.000000' COMMENT '超額收益',
`actual_rate` decimal(20,6) DEFAULT '0.000000' COMMENT '實際收益率',
`third_company_money` decimal(20,6) DEFAULT '0.000000' COMMENT '第三方公司收益',
`load_money` decimal(20,6) DEFAULT '0.000000' COMMENT '借款人利益',
`repayment_time` int(3) DEFAULT '0' COMMENT '還款次數',
`repayment_stage` int(3) DEFAULT '0' COMMENT '當前還款的階段',
`playform_money` decimal(20,6) DEFAULT '0.000000' COMMENT '平臺收益',
`add_datetime` timestamp NOT NULL DEFAULT '2016-04-24 03:49:30' COMMENT '操作時間',
`memo_id_first` int(11) DEFAULT '0' COMMENT '備用id',
`memo_dec_first` decimal(20,6) DEFAULT '0.000000' COMMENT '備用dec',
`memo_str_first` varchar(500) DEFAULT NULL COMMENT '備用str1',
`memo_str_second` varchar(500) DEFAULT NULL COMMENT '備用str2',
`memo_date_first` timestamp NULL DEFAULT '2016-04-24 03:49:30' COMMENT '備用時間1',
`memo_date_second` timestamp NULL DEFAULT '2016-04-24 03:49:30' COMMENT '備用時間2',
`total_repay_money` decimal(20,6) DEFAULT '0.000000' COMMENT '累計還款總額',
`repay_type` int(3) DEFAULT '0' COMMENT '還款型別',
`left_capital_money` decimal(20,6) DEFAULT '0.000000' COMMENT '剩餘本金',
`left_expect_money` decimal(20,6) DEFAULT '0.000000' COMMENT '剩餘收益',
`left_money` decimal(20,6) DEFAULT '0.000000' COMMENT '剩餘留用',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=60 DEFAULT CHARSET=utf8;
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Dumping data for table `rb_repayment_period`
--
LOCK TABLES `rb_repayment_period` WRITE;
/*!40000 ALTER TABLE `rb_repayment_period` DISABLE KEYS */;
INSERT INTO `rb_repayment_period` VALUES (26,160,188,1000.000000,1000.000000,0.000000,0.000000,0.000000,0.000000,0.000000,1,2,0.0000
00,'2016-04-24 07:43:38',0,0.000000,NULL,NULL,'2016-04-24 03:49:30','2016-04-24 03:49:30',0.000000,0,0.000000,0.000000,0.000000),(27
,160,188,100.000000,0.000000,100.000000,0.000000,0.000000,0.000000,0.000000,2,2,0.000000,'2016-04-24 07:45:26',0,0.000000,NULL,NULL,
'2016-04-24 03:49:30','2016-04-24 03:49:30',0.000000,0,0.000000,0.000000,0.000000),(30,160,188,1000.000000,0.000000,87.500000,11.250
000,0.000000,11.250000,890.000000,3,4,0.000000,'2016-04-24 08:09:11',0,0.000000,NULL,NULL,'2016-04-24 03:49:30','2016-04-24 03:49:30
',0.000000,0,0.000000,0.000000,0.000000),(42,163,187,4400.000000,2000.000000,375.000000,0.000000,0.000000,0.000000,2025.000000,1,3,0
.000000,'2016-04-25 07:33:59',0,0.000000,NULL,NULL,'2016-04-25 07:33:59','2016-04-25 07:33:59',0.000000,0,0.000000,0.000000,0.000000
),(47,172,187,10000.000000,2000.000000,375.000000,12.500000,0.000000,12.500000,7600.000000,1,4,0.000000,'2016-04-26 02:48:05',0,0.00
0000,NULL,NULL,'2016-04-26 02:48:05','2016-04-26 02:48:05',0.000000,0,0.000000,0.000000,0.000000),(48,174,187,10000.000000,2000.0000
00,375.000000,12.500000,0.000000,12.500000,7600.000000,1,4,0.000000,'2016-04-26 03:23:41',0,0.000000,NULL,NULL,'2016-04-26 03:23:41'
,'2016-04-26 03:23:41',0.000000,0,0.000000,0.000000,0.000000),(49,157,187,3000.000000,1000.000000,120.000000,0.000000,0.000000,0.000
000,1880.000000,1,3,0.000000,'2016-04-26 03:58:56',0,0.000000,NULL,NULL,'2016-04-26 03:58:56','2016-04-26 03:58:56',3000.000000,2,0.
000000,0.000000,0.000000),(50,175,187,10000.000000,2000.000000,375.000000,12.500000,0.000000,12.500000,7600.000000,1,4,0.000000,'201
6-04-26 05:29:48',0,0.000000,NULL,NULL,'2016-04-26 05:29:48','2016-04-26 05:29:48',10000.000000,2,0.000000,0.000000,0.000000),(54,17
7,187,2000.000000,2000.000000,0.000000,0.000000,0.000000,0.000000,0.000000,1,2,0.000000,'2016-04-27 01:59:35',0,0.000000,NULL,NULL,'
2016-04-27 01:59:35','2016-04-27 01:59:35',2000.000000,1,0.000000,375.000000,0.000000),(55,177,187,4000.000000,0.000000,375.000000,0
.000000,360.000000,0.000000,3625.000000,2,3,0.000000,'2016-04-27 02:01:43',0,0.000000,NULL,NULL,'2016-04-27 02:01:43','2016-04-27 02
:01:43',6000.000000,2,0.000000,0.000000,0.000000),(56,178,187,2100.000000,2000.000000,100.000000,0.000000,0.000000,0.000000,0.000000
,1,2,0.000000,'2016-04-27 03:43:43',0,0.000000,NULL,NULL,'2016-04-27 03:43:43','2016-04-27 03:43:43',2100.000000,1,0.000000,275.0000
00,0.000000),(57,178,187,3000.000000,0.000000,275.000000,0.000000,378.000000,0.000000,2725.000000,2,3,0.000000,'2016-04-27 07:07:34'
,0,0.000000,NULL,NULL,'2016-04-27 07:07:34','2016-04-27 07:07:34',5100.000000,2,0.000000,0.000000,0.000000),(58,181,187,1000.000000,
1000.000000,0.000000,0.000000,0.000000,0.000000,0.000000,1,1,0.000000,'2016-04-27 07:15:58',0,0.000000,NULL,NULL,'2016-04-27 07:15:5
8','2016-04-27 07:15:58',1000.000000,1,1000.000000,375.000000,0.000000),(59,181,187,500.000000,500.000000,0.000000,0.000000,180.0000
00,0.000000,0.000000,2,1,0.000000,'2016-04-27 07:26:34',0,0.000000,NULL,NULL,'2016-04-27 07:26:34','2016-04-27 07:26:34',1500.000000
,1,500.000000,375.000000,0.000000);
rownum的實現
- 環境:
-
mysql> show create table tbl\G;
*************************** 1. row ***************************
Table: tbl
Create Table: CREATE TABLE `tbl` (
`id` int(11) NOT NULL,
`col` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
- mysql> insert into tbl values (1,26),(2,46),(3,35),(4,68),(5,93),(6,92);
-
mysql> select * from tbl
-> ;
+----+------+
| id | col |
+----+------+
| 1 | 26 |
| 2 | 46 |
| 3 | 35 |
| 4 | 68 |
| 5 | 93 |
| 6 | 92 |
+----+------+
6 rows in set (0.00 sec)
-
-
- 實現一:
-
-
mysql> select id,a.col,( select count(*) from tbl b where b.col<=a.col) as rank from tbl a order by rank;
+----+------+------+
| id | col | rank |
+----+------+------+
| 1 | 26 | 1 |
| 3 | 35 | 2 |
| 2 | 46 | 3 |
| 4 | 68 | 4 |
| 6 | 92 | 5 |
| 5 | 93 | 6 |
+----+------+------+
6 rows in set (0.00 sec)
- 瑕疵:當有重複的資料時就有bug了
-
mysql> select id,a.col,(select count(*) from tbl b where b.col<=a.col ) as rank from tbl a order by rank;
+----+------+------+
| id | col | rank |
+----+------+------+
| 1 | 26 | 2 |
| 9 | 26 | 2 |
| 3 | 35 | 4 |
| 8 | 35 | 4 |
| 2 | 46 | 5 |
| 4 | 68 | 6 |
| 6 | 92 | 7 |
| 5 | 93 | 8 |
+----+------+------+
8 rows in set (0.00 sec) -
實現二:解決重複bug(先建立一張數字表Nums(a int) 插入1-100即可)
- 第一步求出個數
-
MySQL [interface_hd_com]> select a.col,COUNT(*) as count,( select count(*) from testtt b where b.col<a.col) as rownum from testtt a group by a.col;
-
+------+-------+--------+
-
| col | count | rownum |
-
+------+-------+--------+
-
| 26 | 1 | 0 |
-
| 35 | 2 | 1 |
-
| 46 | 2 | 3 |
-
| 68 | 2 | 5 |
-
| 92 | 2 | 7 |
-
| 93 | 2 | 9 |
-
+------+-------+--------+
- 6 rows in set (0.00 sec)
第二步:
MySQL [interface_hd_com]> select Nums.a+c.rownum as rank ,col from (select a.col,COUNT(*) as count,( select count(*) from testtt b where b.col<a.col) as rownum from testtt a group by a.col) c,Nums where Nums.a<=count order by col;
+------+------+
| rank | col |
+------+------+
| 1 | 26 |
| 2 | 35 |
| 3 | 35 |
| 4 | 46 |
| 5 | 46 |
| 6 | 68 |
| 7 | 68 |
| 8 | 92 |
| 9 | 92 |
| 10 | 93 |
| 11 | 93 |
+------+------+
11 rows in set (0.01 sec)
連續區間的實現(求連續id區間)
- 第一步:標示
-
mysql> SELECT id,@id:=@id+1 AS alias1 FROM tbl,(SELECT @id:=0) AS id;
+----+--------+
| id | alias1 |
+----+--------+
| 11 | 1 |
| 12 | 2 |
| 13 | 3 |
| 14 | 4 |
| 15 | 5 |
| 16 | 6 |
| 18 | 7 |
| 19 | 8 |
+----+--------+
8 rows in set (0.00 sec)
第二步:計算一下與標示的差值(如果是連續的,那麼差值一樣)
mysql> SELECT id,alias1,(id-alias1) AS diff FROM (SELECT id,@id:=@id+1 AS alias1 FROM tbl,(SELECT @id:=0) AS id) b;
+----+--------+------+
| id | alias1 | diff |
+----+--------+------+
| 11 | 1 | 10 |
| 12 | 2 | 10 |
| 13 | 3 | 10 |
| 14 | 4 | 10 |
| 15 | 5 | 10 |
| 16 | 6 | 10 |
| 18 | 7 | 11 |
| 19 | 8 | 11 |
+----+--------+------+
8 rows in set (0.00 sec)
第三步:根據差值分組找出最大最小即可
mysql> SELECT MIN(id) start_pos,MAX(id) end_pos
-> FROM
-> (SELECT id,alias1,(id-alias1) AS diff FROM (SELECT id,@id:=@id+1 AS alias1 FROM tbl,(SELECT @id:=0) AS id) b)
-> AS c
-> GROUP BY diff;
+-----------+---------+
| start_pos | end_pos |
+-----------+---------+
| 11 | 16 |
| 18 | 19 |
+-----------+---------+
2 rows in set (0.00 sec)
實驗:求tel相同的連續段
-
MySQL [interface_hd_com]> select * from testtab;
-
+------+--------+
-
| id | tel |
-
+------+--------+
-
| 1 | 187163 |
-
| 2 | 187163 |
-
| 3 | 187164 |
-
| 4 | 187164 |
-
| 5 | 187163 |
-
| 6 | 187163 |
-
| 7 | 187164 |
-
| 8 | 187163 |
-
| 9 | 19999 |
-
+------+--------+
- 9 rows in set (0.00 sec)
按照上面的思路求得
MySQL [interface_hd_com]> SELECT MIN(id) start_pos,MAX(id) end_pos,tel FROM (SELECT id,alias1,(id-alias1) AS diff,tel FROM (SELECT id,@id:=@id+1 AS alias1,tel FROM testtab,(SELECT @id:=0) AS id) b) as c GROUP BY diff,tel order by tel desc;
+-----------+---------+--------+
| start_pos | end_pos | tel |
+-----------+---------+--------+
| 3 | 7 | 187164 |
| 1 | 8 | 187163 |
| 9 | 9 | 19999 |
+-----------+---------+--------+ ---這樣是有bug的
發現這樣是不行的,因為id是連續的,所以同一個tel的diff是相同的,但其實中間隔著別的tel
解決辦法:分兩次求在合併
-
MySQL [interface_hd_com]> SELECT MIN(id) start_pos,MAX(id) end_pos,tel FROM (SELECT id,alias1,(id-alias1) AS diff,tel FROM (SELECT id,@id:=@id+1 AS alias1,tel FROM testtab,(SELECT @id:=0) AS id where tel in (SELECT distinct(tel) from testtab where tel<>187164)) b) as c GROUP BY diff,tel order by tel desc;
-
+-----------+---------+--------+
-
| start_pos | end_pos | tel |
-
+-----------+---------+--------+
-
| 1 | 2 | 187163 |
-
| 5 | 6 | 187163 |
-
| 8 | 8 | 187163 |
-
| 9 | 9 | 19999 |
-
+-----------+---------+--------+
-
4 rows in set (0.00 sec)
-
-
MySQL [interface_hd_com]> SELECT MIN(id) start_pos,MAX(id) end_pos,tel FROM (SELECT id,alias1,(id-alias1) AS diff,tel FROM (SELECT id,@id:=@id+1 AS alias1,tel FROM testtab,(SELECT @id:=0) AS id where tel in (187164)) b) as c GROUP BY diff,tel order by tel desc;
-
+-----------+---------+--------+
-
| start_pos | end_pos | tel |
-
+-----------+---------+--------+
-
| 3 | 4 | 187164 |
-
| 7 | 7 | 187164 |
-
+-----------+---------+--------+
- 2 rows in set (0.00 sec)
union 一下
還有一些是其他的部落格寫的方法也不錯:
rownum的實現:http://blog.csdn.net/acmain_chm/article/details/4095531
http://blog.csdn.net/jgmydsai/article/category/3139929
-
mysql> select id,a.col,( select count(*) from tbl b where b.col<=a.col) as rank from tbl a order by rank;
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/29096438/viewspace-2089520/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- sum()over()和count()over()分析函式函式
- MySQL分析函式實現MySql函式
- 13、MySQL Case-MySQL分析函式實現MySql函式
- oracle的分析函式over 及開窗函式Oracle函式
- MySQL中的SUM函式使用教程MySql函式
- MySQL 06 mysql 如何實現類似 oracle 的 merge intoMySqlOracle
- mysql 效果類似split函式MySql函式
- 分析函式 over函式
- oracle分析函式,keep and over解說Oracle函式
- oracle的分析函式over(Partition by...) 及開窗函式Oracle函式
- MySQL的字首索引及Oracle的類似實現MySql索引Oracle
- Oracle分析函式之開窗函式over()詳解Oracle函式
- MySQL 對window函式執行sum函式疑似BugMySql函式
- MySQL排名函式實現MySql函式
- mysql實現oracle的lead和lag函式功能MySqlOracle函式
- Oracle over()函式使用Oracle函式
- mysql實現開窗函式MySql函式
- 【函式】oracle視窗函式over()的理解函式Oracle
- Oracle 中的 ROW_NUMBER() OVER() 分析函式的用法Oracle函式
- MySql中SUM函式計算錯誤問題MySql函式
- mysql自動排序函式dense_rank() over()、rank() over()、row_num() over()用法和區別MySql排序函式
- Oracle統計分析函式集,over(partition by..) 的運用Oracle函式
- oracle的sql查詢分析函式-高階部分-分析函授over()子句OracleSQL函式
- ROW_NUMBER() OVER() 分析函式的用法函式
- oracle over函式 詳解(轉)Oracle函式
- MySQL空間函式實現位置打卡MySql函式
- MySQL自定義變數實現row_number分析函式的天坑MySql變數函式
- mysql與oracle的分組函式MySqlOracle函式
- Oracle 中分析函式用法之--rank(),dense_rank(),partition,over()Oracle函式
- laravel mysql聚合函式使用方法(count,sum,max,min,avg)LaravelMySql函式
- mysql 自定義分析函式 least 及 日期函式MySql函式AST
- MYSQL-實現ORACLE- row_number() over(partition by ) 分組排序功能.MySqlOracle排序
- oracle 與 mysql 中的函式總結OracleMySql函式
- 用ORACLE分析函式實現行列轉換Oracle函式
- MySQL 函式索引功能終於可以實現了MySql函式索引
- Oracle 中 Over() 函式學習總結Oracle函式
- MySQL 函式MySql函式
- MySQL函式MySql函式