创建表T_GOOGS,插入7行语句。
CREATE TABLE T_GOOGS(
GOODS_TYPE VARCHAR2(10),
GOODS_NAME VARCHAR2(20),
PRICE NUMBER(5)
);
INSERT INTO T_GOOGS VALUES('手机','华为mate',2999);
INSERT INTO T_GOOGS VALUES('手机','苹果ipone',7999);
INSERT INTO T_GOOGS VALUES('手机','小米',1999);
INSERT INTO T_GOOGS VALUES('水果','车厘子',79);
INSERT INTO T_GOOGS VALUES('水果','葡萄',79);
INSERT INTO T_GOOGS VALUES('水果','苹果',12);
INSERT INTO T_GOOGS VALUES('电脑','金士顿',499);
SELECT * FROM T_GOOGS;
结果如下图:
现要求:按照价格升序排列,按照价格的前20%,定义为低档;按照价格的20%到85%为中档,剩下的则为高档。
解题思路:
1)分不同的档次,一定要用Case When。
2)前20%如何找出来 -> 小于序号最大值*20% ->创建序号列 ->按照价格升序 -> 分析函数
第一步:新添加一列按价格排序的序号列,用分析函数。
WITH TB AS (
SELECT T.*,ROW_NUMBER()OVER(ORDER BY PRICE) AS RANK_NUM
FROM T_GOOGS T
)
第二步:对比排名数字要小于原表里最大序号的20%,20%-85%,85%以上。
SELECT TB.*
,CASE WHEN RANK_NUM <= (SELECT MAX(RANK_NUM) FROM TB)*0.2 THEN '低档' -- 筛选前20%的物品
WHEN RANK_NUM <= (SELECT MAX(RANK_NUM) FROM TB)*0.85 AND RANK_NUM > (SELECT MAX(RANK_NUM) FROM TB)*0.2 THEN '中档' -- 筛选前20%到85%的物品
ELSE '高档' END AS RANK_Percent -- 剩下的15%物品
FROM TB
最后的结果:
容易犯错的地方:
不能用 Rank_NUM 和 Max(Rank_NUM) 直接比较。
原因:
要返回聚合函数的效果,比如求最大最小值,一定在Select .... From TABLE 里才能展示。
Ntile 分析函数 (指定每个分区必须被划分成的组数 )按照 OVER 子句指定的顺序,较大的组排在较小的组前面。
例如,如果总行数是 53,组数是 5,
不能平均分,则=53/5 + 1先分出去一组,这一组有11行记录。
剩余53-11=42,不能平均分,则 = 42/4+1先分出一组,这一组也有11条记录。
则前三个组每组包含 11 行,其余两个组每组包含 10 行。
另一方面,如果总行数可被组数整除,则行数将在组之间平均分布。例如,如果总行数为 50,有五个组,则每组将包含 10 行。
--- 前20%的
SELECT * FROM
(SELECT T.*,
NTILE(5) OVER(ORDER BY PRICE DESC ) AS GROUP_NUM FROM T_GOOGS T)
WHERE GROUP_NUM =1
原理分析:对整张表划分为5组(也可以将每一个分配记录的数组元素称为“桶”),即每一部分占总比例的20%!
语法:里面的参数要整数形式,但后面保留小数点也不会报错。
-- 相当于Trunc函数,数字直接截取,不用计算四舍五入 --
NTILE (integer_expression) OVER ( [
参考资料:
1.NTILE (Transact-SQL) - SQL Server
2.Sql 四大排名函数(ROW_NUMBER、RANK、DENSE_RANK、NTILE)简介
3.小匿:巩固SQL - 窗口函数&变量&数据透视图