一、题目
二、思路
mysql 8.0有窗口函数可以使用,排序问题一般有3种情况(以3、7、7、9为栗子):
ROW_NUMBER()函数:按顺序求行数,结果为1,2,3,4
RANK()函数:有间隔的分级,结果为1,2,2,4
DENSE_RANK()函数:无间隔的分级,结果为1,2,2,3
窗口函数最关键的是搞明白关键字 PARTITON BY 和 ORDER BY 的作用。
PARTITON BY 是用来分组,即选择要看哪个窗口,类似于 GROUP BY 子句的分组功能,但是 PARTITION BY 子句并不具备 GROUP BY 子句的汇总功能,并不会改变原始表中记录的行数。
ORDER BY 是用来排序,即决定窗口内,是按那种规则(字段)来排序的。
如下的栗子,根据product_type产品类别进行分类,并且在每类产品中进行排序RANK的排序(有间隔的分级排序):
SELECT product_name ,product_type ,sale_price ,RANK() OVER (PARTITION BY product_type ORDER BY sale_price) AS ranking FROM product; +--------------+--------------+------------+---------+ | product_name | product_type | sale_price | ranking | +--------------+--------------+------------+---------+ | 圆珠笔 | 办公用品 | 100 | 1 | | 打孔器 | 办公用品 | 500 | 2 | | 叉子 | 厨房用具 | 500 | 1 | | 擦菜板 | 厨房用具 | 880 | 2 | | 菜刀 | 厨房用具 | 3000 | 3 | | 高压锅 | 厨房用具 | 6800 | 4 | | T恤 | 衣服 | 1000 | 1 | | 运动T恤 | 衣服 | 4000 | 2 | +--------------+--------------+------------+---------+ 8 rows in set (0.00 sec)
回到这题,目标是找到每位玩家第一次登陆的设备。
窗口函数可以很方便实现:对【玩家id】进行分组,每组进行求ROW_NUMBER(按顺序求行数),我们即可得到像上面的分组且组内排序好的结果,然后定位到每组内的第一个元素即可,即where ranknum = 1,不过从结果上看这种做法的时间复杂度稍高,空间复杂度倒好。
三、代码
# Write your MySQL query statement below SELECT player_id, device_id FROM( SELECT player_id, device_id, ROW_NUMBER() OVER (PARTITION BY player_id ORDER BY event_date) AS ranknum FROM Activity)as a WHERE ranknum = 1;