日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

mysql 分析函数_MySQL分析函数实现

發布時間:2024/8/5 数据库 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 mysql 分析函数_MySQL分析函数实现 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

| MySQL分析函數實現

還好MySQL8.0已經實現了與Oracle相同的分析函數。

1. 實現rownum

SET @rn:=0;

SELECT @rn:=@rn+1 AS rownum ,e.* FROM emp e;

或者寫成:

SELECT @rn:=@rn + 1 AS rownum ,e.* FROM emp e ,(SELECT @rn:=0) c

2. 各種分析函數寫法 (MySQL實現分析語句時可能遇到的各種計算問題)

2.1 sum() 實現

--SQL 執行順序 ,FROM ,JOIN ,WHERE ,GROUP BY,HAVING ,ORDER BY ,SELECT,

在Oracle中分頁語句的原始語句如下:

SELECT E.*, SUM(SAL) OVER(PARTITION BY DEPTNO) AS COUNTOVER FROM EMP E;

SELECT E.*,

(SELECT SUMOVER

FROM (SELECT DEPTNO, SUM(SAL) AS SUMOVER

FROM EMP E1

GROUP BY DEPTNO) X

WHERE X.DEPTNO = E.DEPTNO) AS COUNTOVER

FROM EMP E

ORDER BY DEPTNO;

Mysql中也是這么實現的:

SELECT E.*,

(SELECT SUMOVER

FROM (SELECT DEPTNO, SUM(SAL) AS SUMOVER

FROM emp E1

GROUP BY DEPTNO) X

WHERE X.DEPTNO = E.DEPTNO) AS COUNTOVER

FROM emp E

ORDER BY DEPTNO;

2.2 row_number () 實現

select

e.* ,row_number() over(partition by deptno order by empno) as ROW_NUMBER from emp e;

我們的默認規則是在from后初始化變量。

SELECT E.*,

IF(@DEPTNO = DEPTNO, @RN := @RN + 1, @RN := 1) AS ROW_NUMBER,

@DEPTNO := DEPTNO AS VAR1

FROM EMP E, (SELECT @DEPTNO := '', @RN := 0) C

ORDER BY DEPTNO;

SELECT E.*,

IF(@DEPTNO = DEPTNO, @RN := @RN + 1, @RN := 1) AS ROW_NUMBER,

@DEPTNO := DEPTNO AS VAR1

FROM EMP E, (SELECT @DEPTNO := '', @RN := 0) C

ORDER BY DEPTNO;

這個語句首先執行order by

2.3 求每個人員占他所在部門總工資的百分比

在Oracle中實現:

SELECT E.*,

TRUNC(SAL / SUM(SAL) OVER(PARTITION BY DEPTNO), 3) AS SALPERCENT

FROM EMP E

ORDER BY DEPTNO;

SELECT E.*,

SAL / (SELECT SUMOVER

FROM (SELECT DEPTNO, SUM(SAL) AS SUMOVER

FROM emp E1

GROUP BY DEPTNO) X

WHERE X.DEPTNO = E.DEPTNO) AS SalPercent

FROM emp E

ORDER BY DEPTNO;

2.4 求各個部門的總共工資

Oracle:

SELECT e.* ,SUM(sal) OVER(PARTITION BY deptno) FROM emp e;

MySQL:

SELECT A.*,

ROUND(CAST(IF(@DEPTNO = DEPTNO, @MAX := @MAX, @MAX := SUMOVER) AS CHAR ),0) AS SUMOVER2,

@DEPTNO := DEPTNO AS VAR2

FROM (SELECT E.*,

IF(@DEPTNO = DEPTNO, @SUM := @SUM + SAL, @SUM := SAL) AS SUMOVER,

@DEPTNO := DEPTNO AS VAR1

FROM emp E, (SELECT @DEPTNO := '', @SUM := 0, @MAX := 0) C

ORDER BY DEPTNO) A

ORDER BY DEPTNO, SUMOVER DESC;

子查詢的功能實現如下:

下面是這個語句的結果

2.5 拿部門第二的工資的人

首先我們拿第二名的,用Oracle很好實現,不論是第一還是第二。

SELECT *

FROM (SELECT E.*,

ROW_NUMBER() OVER(PARTITION BY DEPTNO ORDER BY SAL DESC) AS RN

FROM EMP E)

WHERE RN = 2;

Mysql中第一這么實現:

在5.6版本,sql_mode非only_full_group_by的情況,我們可以使用如下方式實現

set global sql_mode ='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION';

SELECT * FROM (SELECT e.* FROM emp e ORDER BY deptno,sal ) a GROUP BY deptno;

在SQL_MODE非only_full_group_by時,MySQL中的group by是只取第一行的,下面我們看取第二行的SQL。

SELECT *

FROM (SELECT E.*,

IF(@DEPTNO = DEPTNO, @RN := @RN + 1, @RN := 1) AS RN,

@DEPTNO := DEPTNO

FROM EMP E, (SELECT @RN := 0, @DEPTNO := 0) C

ORDER BY DEPTNO, SAL DESC) X

WHERE X.RN = 2;

2.6 dense_rank()

dense_rank函數返回一個唯一的值,除非當碰到相同數據時,此時所有相同數據的排名都一樣。

SELECT empno,

ename,

sal,

deptno,

rank() OVER(PARTITION BY deptno ORDER BY sal desc) as rank,

dense_rank() OVER(PARTITION BY deptno ORDER BY sal desc) as dense_rank

FROM emp e;

MySQL的寫法:

select

empno,ename,sal,deptno,

if(@deptno = deptno,if(@sal=sal,@rn:=@rn,@rn3:=@rn3+1),@rn:=1) as "RANK() OVER",

if(@sal =sal,@rn2:=@rn2 ,if(@deptno = deptno,@rn2:=@rn2+1,@rn2:=1)) as "DENSE_RANK() OVER",

if(@deptno = deptno,@rn:=@rn+1,@rn:=1) as "ROW_NUMBER() OVER"

, @deptno:=deptno,@sal:=sal

from

(select empno,ename,sal,deptno from emp a ,(select @rn:=1,@deptno:=0,@rn2:=0,@rn3:=0,@sal:=0,@i:=0) b order by deptno,sal desc) c;

2.7 連續獲得冠軍的有哪些

--請寫出一條SQL語句,查詢出在此期間連續獲得冠軍的有哪些,其連續的年份的起止時間是多少,結果如下:

create table nba as

SELECT '公牛' AS TEAM, '1991' AS Y FROM DUAL UNION ALL

SELECT '公牛' AS TEAM, '1992' AS Y FROM DUAL UNION ALL

SELECT '公牛' AS TEAM, '1993' AS Y FROM DUAL UNION ALL

SELECT '活塞' AS TEAM, '1990' AS Y FROM DUAL UNION ALL

SELECT '火箭' AS TEAM, '1994' AS Y FROM DUAL UNION ALL

SELECT '火箭' AS TEAM, '1995' AS Y FROM DUAL UNION ALL

SELECT '公牛' AS TEAM, '1996' AS Y FROM DUAL UNION ALL

SELECT '公牛' AS TEAM, '1997' AS Y FROM DUAL UNION ALL

SELECT '公牛' AS TEAM, '1998' AS Y FROM DUAL UNION ALL

SELECT '馬刺' AS TEAM, '1999' AS Y FROM DUAL UNION ALL

SELECT '湖人' AS TEAM, '2000' AS Y FROM DUAL UNION ALL

SELECT '湖人' AS TEAM, '2001' AS Y FROM DUAL UNION ALL

SELECT '湖人' AS TEAM, '2002' AS Y FROM DUAL UNION ALL

SELECT '馬刺' AS TEAM, '2003' AS Y FROM DUAL UNION ALL

SELECT '活塞' AS TEAM, '2004' AS Y FROM DUAL UNION ALL

SELECT '馬刺' AS TEAM, '2005' AS Y FROM DUAL UNION ALL

SELECT '熱火' AS TEAM, '2006' AS Y FROM DUAL UNION ALL

SELECT '馬刺' AS TEAM, '2007' AS Y FROM DUAL UNION ALL

SELECT '凱爾特人' AS TEAM, '2008' AS Y FROM DUAL UNION ALL

SELECT '湖人' AS TEAM, '2009' AS Y FROM DUAL UNION ALL

SELECT '湖人' AS TEAM, '2010' AS Y FROM DUAL;

Oracle實現:

SELECT TEAM, MIN(Y), MAX(Y)

FROM (SELECT E.*,

ROWNUM,

ROW_NUMBER() OVER(PARTITION BY TEAM ORDER BY Y) AS RN,

ROWNUM - ROW_NUMBER() OVER(PARTITION BY TEAM ORDER BY Y) AS DIFF

FROM NBA E

ORDER BY Y)

GROUP BY TEAM, DIFF

HAVING MIN(Y) != MAX(Y)

ORDER BY 2;

MySQL實現:

SELECT TEAM, MIN(Y), MAX(Y)

FROM (SELECT TEAM,

Y,

IF(@TEAM = TEAM, @RN := @RN + 1, @RN := 1) AS RWN,

@RN1 := @RN1 + 1 AS RN,

@TEAM := TEAM

FROM nba N, (SELECT @RN := 0, @TEAM := '', @RN1 := '') C) A

GROUP BY RN - RWN

HAVING MIN(Y) != MAX(Y)

ORDER BY 2

| UDF插件

Userdefined Function,用戶定義函數。我們知道,MySQL本身支持很多內建的函數,此外還可以通過創建存儲方法來定義函數。UDF為用戶提供了一種更高效的方式來創建函數。

UDF與普通函數類似,有參數,也有輸出。分為兩種類型:單次調用型和聚集函數。前者能夠針對每一行數據進行處理,后者則用于處理Group By這樣的情況。

UDF自定義函數,在MySQL basedir/include

[root@test12c include]# pwd

/usr/local/mysql/include

[root@test12c include]# cat rownum.c

#include

#include

#if defined(MYSQL_SERVER)

#include /* To get strmov() */

#else

/* when compiled as standalone */

#include

#define strmov(a,b) stpcpy(a,b)

#endif

#include

#include

/*

gcc -fPIC -Wall -I/usr/local/mysql/include -I. -shared rownum.c -o rownum.so

DROP FUNCTION IF EXISTS rownum;

CREATE FUNCTION rownum RETURNS INTEGER SONAME 'rownum.so';

*/

C_MODE_START;

my_bool rownum_init(UDF_INIT *initid, UDF_ARGS *args, char *message);

void rownum_deinit(UDF_INIT *initid);

chong rownum(UDF_INIT *initid, UDF_ARGS *args, char *is_null,char *error);

C_MODE_END;

/*

Simple example of how to get a sequences starting from the first argument

or 1 if no arguments have been given

*/

my_bool rownum_init(UDF_INIT *initid, UDF_ARGS *args, char *message)

{

if (args->arg_count > 1)

{

strmov(message,"This function takes none or 1 argument");

return 1;

}

if (args->arg_count)

args->arg_type[0]= INT_RESULT; /* Force argument to int */

if (!(initid->ptr=(char*) malloc(sizeof(chong))))

{

strmov(message,"Couldn't allocate memory");

return 1;

}

memset(initid->ptr, 0, sizeof(chong));

initid->const_item=0;

return 0;

}

void rownum_deinit(UDF_INIT *initid)

{

if (initid->ptr)

free(initid->ptr);

}

chong rownum(UDF_INIT *initid __attribute__((unused)), UDF_ARGS *args,char *is_null __attribute__((unused)),char *error __attribute__((unused)))

{

uchong val=0;

if (args->arg_count)

val= *((chong*) args->args[0]);

return ++*((chong*) initid->ptr) + val;

}

生成動態鏈接庫

gcc rownum.c -fPIC -shared -o ../lib/plugin/rownum.so

| ?作者簡介

姚崇·沃趣科技高級數據庫技術專家

熟悉Oracle、MySQL數據庫內部機制,豐富的Oracle、MySQL故障診斷、性能調優、數據庫備份恢復、復制、高可用方案及遷移經驗。

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

作者:woqutechteam

來源:CSDN

原文:https://blog.csdn.net/woqutechteam/article/details/83501038

版權聲明:本文為博主原創文章,轉載請附上博文鏈接!

總結

以上是生活随笔為你收集整理的mysql 分析函数_MySQL分析函数实现的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。