2.18 sql排序查询(ORDER BY、ASC、DESC)

张开发
2026/4/16 4:52:52 15 分钟阅读

分享文章

2.18 sql排序查询(ORDER BY、ASC、DESC)
2.18 排序查询ORDER BY、ASC、DESC在电商数据分析中你几乎每天都要用到排序销量排行榜TOP10商品。高价值用户排行消费金额最高的用户。最新订单优先显示按时间倒序。活动效果对比按ROI排序。ORDER BY子句就是用来做排序的。这一章我会带你彻底搞懂ORDER BY的各种用法单字段排序、多字段排序、按表达式排序、与LIMIT配合取TOP N。学完之后你能轻松做出各类排行榜和优先级分析。学习前准备已完成MySQL安装参考系列前几章已安装DBeaver或Navicat准备一个练习数据库比如orderby_demo学习前环境准备步骤1确保MySQL服务已启动。步骤2创建练习数据库和表并插入示例数据。CREATEDATABASEorderby_demoCHARACTERSETutf8mb4COLLATEutf8mb4_unicode_ci;USEorderby_demo;-- 订单表包含用户、店铺、金额、销量、时间等CREATETABLEorders(order_idVARCHAR(50)PRIMARYKEY,user_idINTNOTNULL,shop_nameVARCHAR(50)NOTNULL,product_nameVARCHAR(100),amountDECIMAL(10,2)NOTNULL,quantityINTNOTNULLDEFAULT1,order_statusVARCHAR(20)NOTNULL,create_timeDATETIMENOTNULL);INSERTINTOordersVALUES(ORD001,1001,女装旗舰店,碎花连衣裙,299.00,2,已支付,2025-06-01 10:00:00),(ORD002,1002,女装旗舰店,纯棉T恤,189.00,3,已取消,2025-06-01 11:00:00),(ORD003,1003,男装专营店,牛仔裤,599.00,1,已支付,2025-06-02 09:30:00),(ORD004,1001,女装旗舰店,雪纺衫,399.00,1,已支付,2025-06-03 14:20:00),(ORD005,1004,童装店,儿童T恤,99.00,5,已完成,2025-06-03 16:00:00),(ORD006,1005,女装旗舰店,真丝连衣裙,1299.00,1,已支付,2025-06-04 08:30:00),(ORD007,1002,男装专营店,休闲短裤,89.00,2,已取消,2025-06-04 10:00:00),(ORD008,1006,女装旗舰店,基础打底衫,89.00,10,已支付,2025-06-05 09:00:00),(ORD009,1007,男装专营店,Polo衫,259.00,1,已支付,2025-06-05 14:00:00);ORDER BY排序基础认知ORDER BY子句用于对查询结果集进行排序。它通常放在SQL语句的末尾LIMIT之前。基本语法SELECT列FROM表ORDERBY列1[ASC|DESC],列2[ASC|DESC],...;ASC升序默认从小到大从早到晚。DESC降序从大到小从晚到早。在电商数据分析中的核心用途找出销量最高的商品ORDER BY quantity DESC。找出消费金额最高的用户ORDER BY amount DESC。最新订单优先ORDER BY create_time DESC。结合LIMIT做TOP N分析。我的踩坑经历第一次用ORDER BY时我写了ORDER BY amount结果金额最小的排在最前面。我以为默认是降序其实默认是升序。要降序必须写DESC。单字段排序4.1 基础语法SELECT*FROM表ORDERBY列名[ASC|DESC];4.2 电商实操案例案例一按订单金额升序从低到高SELECTorder_id,amountFROMordersORDERBYamount;预期结果89, 89, 99, 189, 259, 299, 399, 599, 1299。案例二按订单金额降序从高到低SELECTorder_id,amountFROMordersORDERBYamountDESC;预期结果1299, 599, 399, 299, 259, 189, 99, 89, 89。案例三按下单时间降序最新订单在前SELECTorder_id,create_timeFROMordersORDERBYcreate_timeDESC;预期结果ORD009(6月5日), ORD008(6月5日), ORD007(6月4日), ORD006(6月4日), ORD005(6月3日), ORD004(6月3日), ORD003(6月2日), ORD002(6月1日), ORD001(6月1日)。4.3 分步操作先写不带ORDER BY的查询看原始顺序通常按主键或插入顺序。加上ORDER BY指定字段。决定升序还是降序。执行并观察顺序变化。避坑提醒字符串类型的数字排序可能不符合预期如’10’ ‘2’。确保数据类型正确。ORDER BY可以使用不在SELECT列表中的列。实操避坑提醒如果对文本字段排序MySQL默认不区分大小写但区分字符集。如果要按拼音排序可能需要设置排序规则COLLATE。多字段联合排序5.1 基础语法SELECT*FROM表ORDERBY列1[ASC|DESC],列2[ASC|DESC],...;先按第一列排序第一列相同再按第二列以此类推。5.2 电商实操案例案例一先按店铺名称升序再按订单金额降序同一店铺内金额高的在前SELECTshop_name,amountFROMordersORDERBYshop_nameASC,amountDESC;预期结果女装旗舰店1299, 399, 299, 189, 89男装专营店599, 259, 89童装店99案例二先按订单状态已支付在前再按金额降序SELECTorder_status,amountFROMordersORDERBYorder_status已支付DESC,amountDESC;注意这里用了表达式后面会讲也可以直接用CASE。简单方式先按状态分组再按金额排序。SELECTorder_status,amountFROMordersORDERBYCASEorder_statusWHEN已支付THEN1WHEN已完成THEN2WHEN已取消THEN3ELSE4END,amountDESC;5.3 分步操作确定第一排序字段和方向。确定第二排序字段和方向。依次写在ORDER BY后面用逗号分隔。执行验证。避坑提醒多字段排序时每个字段都要单独指定方向如果不写默认ASC。NULL值的排序MySQL中NULL被视为最小值升序排在最前降序排在最后。我的踩坑经历我写过ORDER BY shop_name, amount DESC以为先按店铺升序再按金额降序。但实际是shop_name升序amount也升序因为没写DESC。后来改成ORDER BY shop_name, amount DESC才正确。表达式与别名排序6.1 基础语法可以对表达式计算字段排序也可以对列别名排序。SELECT列,表达式AS别名FROM表ORDERBY表达式;SELECT列,表达式AS别名FROM表ORDERBY别名;6.2 电商实操案例案例一按订单总价金额×数量降序SELECTorder_id,amount,quantity,amount*quantityAStotal_valueFROMordersORDERBYtotal_valueDESC;预期结果ORD008(8910890), ORD006(129911299) — 1299 890所以ORD006第一ORD008第二。案例二按商品毛利率排序假设有成本表这里用简化没有成本字段演示表达式排序。SELECTproduct_name,amount,amount*0.6ASestimated_profitFROMordersORDERBYestimated_profitDESC;案例三按订单日期只取月份排序SELECTorder_id,create_time,MONTH(create_time)ASmonth_numFROMordersORDERBYmonth_num;6.3 分步操作先写出带表达式的查询确认表达式正确。在ORDER BY中直接写表达式或别名。执行验证。避坑提醒表达式排序可能会影响性能因为要对每一行计算。别名在ORDER BY中可用因为ORDER BY在SELECT之后执行但在WHERE中不可用。我的踩坑经历我写过SELECT amount * quantity AS total FROM orders ORDER BY total没问题。但后来想在WHERE中用WHERE total 1000结果报错。因为WHERE在SELECT之前执行别名还不存在。排序与条件筛选的配合7.1 基础语法WHERE先过滤行ORDER BY再对结果排序。SELECT*FROM表WHERE条件ORDERBY列;7.2 电商实操案例案例一查询女装旗舰店已支付订单按金额降序SELECTorder_id,shop_name,amountFROMordersWHEREshop_name女装旗舰店ANDorder_status已支付ORDERBYamountDESC;预期结果1299, 399, 299, 89ORD008的89。案例二查询6月份金额大于200的订单按时间升序SELECTorder_id,amount,create_timeFROMordersWHEREamount200ANDcreate_timeBETWEEN2025-06-01AND2025-06-30ORDERBYcreate_timeASC;预期结果ORD001(299), ORD003(599), ORD004(399), ORD006(1299), ORD009(259)。案例三销量TOP 3的商品按数量降序取前3SELECTproduct_name,quantityFROMordersORDERBYquantityDESCLIMIT3;预期结果基础打底衫(10), 儿童T恤(5), 纯棉T恤(3)。7.3 分步操作先写WHERE条件筛选出目标数据。加上ORDER BY排序。可选加上LIMIT限制行数。执行验证。避坑提醒ORDER BY一定要放在LIMIT前面否则语法错误。LIMIT是在排序之后取前N行所以必须先排序再限制。实操避坑提醒如果要对分组后的结果排序如每个类目下的商品销量排名需要用到窗口函数ROW_NUMBER()普通ORDER BY只能全局排序。综合实操案例服饰类目店铺月度商品销量TOP榜与用户消费排行8.1 案例背景某服饰类目店铺需要生成以下排行榜商品销量TOP 5按总销量quantity降序。高价值用户消费排行按用户总消费金额降序需聚合。女装类目中按销售额排序金额*数量的TOP 3商品。最新订单优先显示按时间倒序同时按金额降序相同时间金额高的在前。8.2 分步操作步骤1商品销量TOP 5不考虑聚合直接按订单中的数量排序SELECTproduct_name,quantityFROMordersWHEREproduct_nameISNOTNULLORDERBYquantityDESCLIMIT5;预期结果基础打底衫(10), 儿童T恤(5), 纯棉T恤(3), 碎花连衣裙(2), 休闲短裤(2)。步骤2高价值用户消费排行需要按用户分组聚合SELECTuser_id,SUM(amount)AStotal_spentFROMordersWHEREorder_statusIN(已支付,已完成)GROUPBYuser_idORDERBYtotal_spentDESC;预期结果1005(1299), 1001(299399698), 1003(599), 1007(259), 1006(89), 1004(99? 99小于89? 实际1004童装店99元但ORD005是已完成应该计入所以100499100689顺序1005,1001,1003,1007,1004,1006。还有1002? 1002订单都是已取消不计入所以不出现。步骤3女装类目中销售额金额×数量TOP 3SELECTproduct_name,amount,quantity,amount*quantityASsalesFROMordersWHEREshop_name女装旗舰店ORDERBYsalesDESCLIMIT3;预期结果ORD008(基础打底衫 8910890), ORD006(真丝连衣裙129911299), 实际上1299890所以ORD006第一ORD008第二ORD004(399*1399)第三。步骤4最新订单优先同时按金额降序SELECTorder_id,create_time,amountFROMordersORDERBYcreate_timeDESC,amountDESC;预期结果同一时间6月5日ORD009(259)和ORD008(89)金额大的在前ORD009, ORD0086月4日ORD006(1299), ORD007(89) → ORD006, ORD007依此类推。8.3 结果验证执行所有查询检查逻辑一致性如TOP 5数量正确排序顺序正确。 电商数据合规提示在用户消费排行中user_id是内部匿名ID不涉及个人敏感信息。但如果用户表关联了手机号绝对不要在排行榜中输出手机号。另外销量TOP榜涉及商品明细属于经营数据分享时注意保密。本章踩坑清单与合规总结9.1 新手常见踩坑错误原因正确做法忘记写DESC导致升序默认ASC明确指定方向多字段排序时方向写错位置语法错误每个字段单独跟ASC/DESCORDER BY放在LIMIT后面语法错误ORDER BY必须在LIMIT之前对表达式排序时写了重复计算可读性差用别名简化对文本数字排序结果奇怪数据类型问题转为数值再排序9.2 性能优化建议为经常排序的字段建立索引如create_time。大表排序时尽量配合WHERE缩小范围。避免对非索引字段排序会导致文件排序filesort。结语ORDER BY是SQL中让数据“有序”的关键。掌握单字段、多字段、表达式排序以及与LIMIT配合你就能轻松做出各类排行榜和优先级分析。有问题的评论区留言我看到会回复。

更多文章