SQL入门:基于其他列总和筛选数据行
嘿,我明白你想要做的事——基于商品的总销量、总销售额这类聚合后的数值,来筛选出符合条件的原始销售数据行对吧?结合你给出的示例数据表,我给你整理几个实用的解决方案:
你的示例数据表
| Name | Sell_Date | Price | Quantity |
|---|---|---|---|
| Doll | 14-JAN-2005 | 12 | 2 |
| Bike | 07-FEB-2013 | 450 | 1 |
| Doll | 15-SEP-2016 | 12 | 5 |
场景1:筛选总销量达标的商品的所有销售记录
比如你想找出总销量≥6的商品的每一条销售数据,这里要注意:不能直接用WHERE子句筛选聚合值(因为WHERE是在聚合前筛选单行数据),得用下面两种方法:
方法1:子查询 + IN 子句
先找出符合总销量要求的商品名称,再匹配原始数据:
SELECT * FROM sales_table -- 替换成你的实际表名 WHERE Name IN ( SELECT Name FROM sales_table GROUP BY Name HAVING SUM(Quantity) >= 6 );
这个查询会先算出每个商品的总销量(Doll总销量7,Bike总销量1),筛选出总销量≥6的Doll,然后返回Doll的两条原始销售记录。
方法2:窗口函数(更灵活,可展示聚合值)
如果想在结果里同时看到该商品的总销量,用窗口函数最合适,它不会改变原始行的结构:
SELECT Name, Sell_Date, Price, Quantity, total_quantity FROM ( SELECT *, SUM(Quantity) OVER (PARTITION BY Name) AS total_quantity FROM sales_table ) AS sub_query WHERE total_quantity >= 6;
返回的结果会多一列total_quantity,清晰显示对应商品的总销量,同时筛选出符合条件的行。
场景2:筛选总销售额达标的商品的销售记录
总销售额是Price * Quantity的总和,比如你想找总销售额≥80的商品记录,逻辑和上面类似:
子查询方式
SELECT * FROM sales_table WHERE Name IN ( SELECT Name FROM sales_table GROUP BY Name HAVING SUM(Price * Quantity) >= 80 );
这里Doll的总销售额是(122)+(125)=84,符合条件,所以会返回它的两条记录;Bike总销售额450,若把阈值设为500,就不会返回它。
窗口函数方式
SELECT Name, Sell_Date, Price, Quantity, total_revenue FROM ( SELECT *, SUM(Price * Quantity) OVER (PARTITION BY Name) AS total_revenue FROM sales_table ) AS sub_query WHERE total_revenue >= 80;
这个结果会同时展示每个商品的总销售额,方便你核对数据。
关键知识点提醒
WHERE子句无法直接使用SUM()这类聚合函数,因为它是在分组聚合前筛选单行;HAVING子句必须配合GROUP BY使用,用来筛选聚合后的分组;- 窗口函数适合需要保留原始行结构,同时计算分组聚合值的场景,比子查询更直观。
内容的提问来源于stack exchange,提问作者Deathcofi




