1. 程式人生 > >用mysql實現oracle的分析函式

用mysql實現oracle的分析函式

最近資料中心環境切換,源資料儲存在oracle11g裡,新環境要mysql5.7, 由於很多的sql語句用到了oracle的分析函式,而mysql對此暫無很好的支援,所以做了以下的轉化,作為標記,有錯誤的地方,希望大家指正。

一。準備工作

1.資料表準備

oracle的scott使用者下,有emp表,我這裡基於它進行驗證

(1)mysql建表語句

CREATE TABLE `emp` (
`empno` DECIMAL(4,0) NOT NULL,
`ename` VARCHAR(10) NULL DEFAULT NULL,
`job` VARCHAR(9) NULL DEFAULT NULL,
`mgr` DECIMAL(4,0) NULL DEFAULT NULL,
`hiredate` DATE NULL DEFAULT NULL,
`sal` DECIMAL(7,2) NULL DEFAULT NULL,
`comm` DECIMAL(7,2) NULL DEFAULT NULL,
`deptno` DECIMAL(2,0) NULL DEFAULT NULL
)
COLLATE='utf8_general_ci'
ENGINE=InnoDB
;


(2)資料準備

INSERT INTO `emp` VALUES (7369, 'SMITH', 'CLERK', 7902, '1980-12-17', 800.00, 0.00, 20);
INSERT INTO `emp` VALUES (7499, 'ALLEN', 'SALESMAN', 7698, '1981-02-20', 1600.00, 300.00, 30);
INSERT INTO `emp` VALUES (7521, 'WARD', 'SALESMAN', 7698, '1981-02-22', 1250.00, 500.00, 30);
INSERT INTO `emp` VALUES (7566, 'JONES', 'MANAGER', 7839, '1981-04-02', 2975.00, 0.00, 20);
INSERT INTO `emp` VALUES (7654, 'MARTIN', 'SALESMAN', 7698, '1981-09-28', 1250.00, 1400.00, 30);
INSERT INTO `emp` VALUES (7698, 'BLAKE', 'MANAGER', 7839, '1981-05-01', 2850.00, 0.00, 30);
INSERT INTO `emp` VALUES (7782, 'CLARK', 'MANAGER', 7839, '1981-06-09', 2450.00, 0.00, 10);
INSERT INTO `emp` VALUES (7788, 'SCOTT', 'ANALYST', 7566, '1987-04-19', 3000.00, 0.00, 20);
INSERT INTO `emp` VALUES (7839, 'KING', 'PRESIDENT', 0, '1981-11-17', 5000.00, 0.00, 10);
INSERT INTO `emp` VALUES (7844, 'TURNER', 'SALESMAN', 7698, '1981-09-08', 1500.00, 0.00, 30);
INSERT INTO `emp` VALUES (7876, 'ADAMS', 'CLERK', 7788, '1987-05-23', 1100.00, 0.00, 20);
INSERT INTO `emp` VALUES (7900, 'JAMES', 'CLERK', 7698, '1981-12-03', 950.00, 0.00, 30);
INSERT INTO `emp` VALUES (7902, 'FORD', 'ANALYST', 7566, '1981-12-03', 3000.00, 0.00, 20);
INSERT INTO `emp` VALUES (7934, 'MILLER', 'CLERK', 7782, '1982-01-23', 1300.00, 0.00, 10);


---------------------------------------------------------------------

1.oracle  row_number over-》mysql自定義變數
(1)oracle

select deptno,sal,row_number() over(partition by deptno order by sal) rownumber from scott.emp


(2)mysql
select 
tmp.deptno,
tmp.sal,
IF (@deptno = tmp.deptno,@rownumber:[email protected]
+ 1,@rownumber:= 1) AS rownumber,
@deptno := tmp.deptno as dtno
FROM
(
SELECT deptno,sal FROM emp
ORDER BY deptno,sal
) tmp,

(SELECT @deptno := NULL,@rownumber:= 0) a


-------------------------------------------------------------------
2.oracle first_value ->mysql自定義變數
(1)oracle
SELECT DEPTNO,
       JOB,
       SAL,
       FIRST_VALUE(SAL) OVER(PARTITION BY DEPTNO ORDER BY DEPTNO) firstvalue

  FROM scott.EMP


(2)mysql
select a.DEPTNO,a.JOB,a.SAL,m.sal
from emp a left outer join 
(
SELECT DEPTNO,JOB,SAL
from 
(
SELECT DEPTNO,
       JOB,
       SAL,
       @num := if(@DEPTNO = DEPTNO, @num + 1, 1) as row_number,
@DEPTNO := DEPTNO as dummy
  FROM emp
  order by DEPTNO,SAL
  ) x
  where x.row_number=1
  order by DEPTNO,SAL
  ) m

  on a.deptno = m.deptno


-------------------------------------------------------------------
3.ratio_to_report的oracle-》mysql
(1)oracle
SELECT  
empno,ename,sal,deptno,  
   ratio_to_report(sal) over () as pct1l,    
     ratio_to_report(sal) over (partition by deptno) as pct2  

    FROM scott.emp; 


(2)mysql
select a.DEPTNO,a.JOB,a.SAL,a.sal/m.s
from emp a left outer join 
(
select sal,deptno,sum(sal) as s
from emp 
group by DEPTNO
) m
  on a.deptno = m.deptno

  order by a.DEPTNO


-------------------------------------------------------------------
4.max,min,avg,count over -> mysql
(1)oracle
SELECT  deptno,
     max(sal) over (partition by deptno) as maxsal,
     min(sal) over (partition by deptno) as minsal,
     avg(sal) over (partition by deptno) as avgsal,
      count(sal) over (partition by deptno) as maxsal  

    FROM scott.emp; 


(2)mysql
SELECT a.deptno,m.maxsal,m.minsal,m.avgsal,m.countsal
FROM emp a
LEFT OUTER
JOIN (
SELECT deptno,MAX(sal) maxsal,MIN(sal) minsal,AVG(sal) avgsal,COUNT(sal) countsal
FROM emp
GROUP BY deptno
) m ON a.deptno = m.deptno

order by a.deptno


5.用row_number實現oracle的lag函式

(1)oracle

select deptno,sal,lag(sal,1) over(partition by deptno order by sal) from scott.emp


(2)mysql

select main.deptno,main.rownumber,main.sal,ano.sal as lagsal,ano.rownumber
from
(
select
tmp.deptno,
tmp.sal,
IF (@deptno = tmp.deptno,@rownumber:[email protected]+ 1,@rownumber:= 1) AS rownumber,
@deptno := tmp.deptno as dtno
FROM
(
SELECT deptno,sal FROM emp
ORDER BY deptno,sal
) tmp,
(SELECT @deptno := NULL,@rownumber:= 0) a
) main left join 
(
select
tmp.deptno,
tmp.sal,
IF (@deptno = tmp.deptno,@rownumber:[email protected]+ 1,@rownumber:= 1) AS rownumber,
@deptno := tmp.deptno as dtno
FROM
(
SELECT deptno,sal FROM emp
ORDER BY deptno,sal
) tmp,
(SELECT @deptno := NULL,@rownumber:= 0) a
) ano
on main.deptno=ano.deptno and ano.rownumber=main.rownumber-1


-----------------------------------------------------------------