mysql 用一条sql按多个条件分组统计

本文是一篇SQL查询示例,用于统计不同年龄段和性别的人员数量,数据来源于某会员表和劳动关系表,主要关注在职员工的年龄分布情况。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

示例:按年龄和性别分组统计人员

SELECT
	a.sex,
	a.nld AS ageGroup,
	count( 1 ) AS people 
FROM
	(
	SELECT
		td.sex,
	CASE
			
			WHEN td.age >= 18 
			AND td.age <= 30 AND td.sex = '1' THEN '18-30' WHEN td.age >= 18 
				AND td.age <= 30 AND td.sex = '2' THEN '18-30' WHEN td.age >= 31 
					AND td.age <= 40 AND td.sex = '1' THEN '31-40' WHEN td.age >= 31 
						AND td.age <= 40 AND td.sex = '2' THEN '31-40' WHEN td.age >= 41 
							AND td.age <= 50 AND td.sex = '1' THEN '41-50' WHEN td.age >= 41 
								AND td.age <= 50 AND td.sex = '2' THEN '41-50' WHEN td.age >= 51 
									AND td.age <= 55 AND td.sex = '1' THEN '51-55' WHEN td.age >= 51 
										AND td.age <= 55 AND td.sex = '2' THEN '51-55' WHEN td.age >= 56 
											AND td.age < 60 AND td.sex = '1' THEN '56-60' WHEN td.age >= 56 
												AND td.age < 60 AND td.sex = '2' THEN '56-60' WHEN td.age >= 60 
													AND td.sex = '1' THEN
														'60以上' 
														WHEN td.age >= 60 
														AND td.sex = '2' THEN
															'60以上' 
															END AS nld 
													FROM
														(
														SELECT
															m.sex,
															m.card_no,
															m.birth_date,
															FLOOR( PERIOD_DIFF( DATE_FORMAT( NOW(), '%Y%m' ), DATE_FORMAT( CONCAT( m.birth_date, '-01' ), '%Y%m' ))/ 12 ) AS age 
														FROM
															tb_cloud_member m
															LEFT JOIN tb_cloud_laborun l ON l.laborun_code = m.laborun_code
															LEFT JOIN tb_cloud_enterprises tce ON tce.id = m.unit_id 
															AND l.is_deleted = 0 
															AND tce.is_deleted = 0 
														WHERE
															1 = 1 
															AND m.is_deleted = 0 
															AND l.is_laborun = 1 
															AND m.is_new_occupation = 2 
															AND ( m.retirement_flag IS NULL OR m.retirement_flag = '' OR m.retirement_flag = '0' OR m.retirement_flag = '2' ) 
															AND (
																m.job_status IS NULL 
															OR m.job_status NOT IN ( 4, 5, 6 ))) td 
													) a 
												WHERE
													a.nld IS NOT NULL 
												GROUP BY
													nld,
												a.sex;
<think>我们讨论的是如何将一条SQL查询的结果数量(即行数)作为另一条SQL查询的条件。常见的方法有:1.使用子查询:在WHERE子句中嵌套一个返回单值的子查询(例如COUNT(*))2.使用变量:先执行第一条查询,将结果存入变量,然后在第二条查询中使用该变量3.使用临表:将第一条查询的结果存入临表,然后在第二条查询中引用临根据问题描述,用户希望将“一条SQL查询的结果数量”作为条件,即我们关注的是第一条查询返回的行数(COUNT值),而不是具体的行数据。例如:假设我们有两个表:订单表(orders)和客户表(customers)需求:查询那些订单数量超过10个的客户信息步骤:1.先计算每个客户的订单数量2.然后筛选出订单数量>10的客户3.最后获取这些客户的详细信息但这里我们不需要分两步执行,可以用一条SQL完成(使用HAVING子句或子查询)。然而,如果用户确实需要将两个独立的SQL串联(比如第一个SQL的结果数量作为第二个SQL的输入条件),我们可以这样:情况1:第一个查询返回一个单一数值(如总数)例如:第一个SQL:SELECTCOUNT(*)FROMordersWHEREcustomer_id=1;然后我们得到数量n,如果n>10,则在第二个SQL中查询该客户的信息。但是,我们想要在一条SQL语句中完成,或者通过子查询将第一个查询的结果直接作为第二个查询的条件。然而,如果第一个查询返回的是多个数值(比如多个客户ID),我们通常用IN子句。但这里用户明确要求的是“数量结果”,即一个数值。因此,我们考虑子查询返回单个值(标量子查询)的情况。示例:查询订单数量大于10的客户信息方法1:使用子查询和HAVING但是注意:这里我们可以在一个查询中完成,不需要拆成两个查询。如果一定要拆成两个查询(即先获取订单数量,再用这个数量作为条件去查客户),那么我们可以这样:第一步:获取某个客户(比如客户1)的订单数量SELECTCOUNT(*)ASorder_countFROMordersWHEREcustomer_id=1;第二步:如果order_count>10,则查询该客户的信息SELECT*FROMcustomersWHEREcustomer_id=1;但是,这样需要执行两次。如何合并成一次?我们可以这样:SELECT*FROMcustomersWHERE(SELECTCOUNT(*)FROMordersWHEREorders.customer_id=customers.customer_id)>10;然而,这实际上是关联子查询,对于每个客户都会执行一次子查询,效率可能不高。另一种方式:使用GROUPBY和HAVING先筛选出订单数量>10的客户ID,然后再关联客户表。SELECTc.*FROMcustomerscINNERJOIN(SELECTcustomer_idFROMordersGROUPBYcustomer_idHAVINGCOUNT(*)>10)tONc.customer_id=t.customer_id;但是,用户的问题是将“第一条SQL的数量结果”作为第二条SQL条件,即第一个查询的结果是一个数值(比如10),然后第二个查询使用这个数值(比如查询订单数量大于这个数值的客户)。例如:第一个SQL:获取平均订单数量(比如10),然后第二个SQL:查询订单数量大于10的客户。这,我们可以这样:第一步:计算平均订单数量SELECTAVG(order_count)FROM(SELECTCOUNT(*)ASorder_countFROMordersGROUPBYcustomer_id)t;第二步:使用这个平均值作为条件SELECTcustomer_idFROMordersGROUPBYcustomer_idHAVINGCOUNT(*)>(第一步的结果)如何合并成一条SQL?我们可以使用子查询:SELECTcustomer_idFROMordersGROUPBYcustomer_idHAVINGCOUNT(*)>(SELECTAVG(order_count)FROM(SELECTCOUNT(*)ASorder_countFROMordersGROUPBYcustomer_id)t);注意:这里嵌套了两层子查询,可能效率不高,但实现了需求。因此,根据具体场景,我们可以将第一个查询(返回一个数值)作为子查询嵌入到第二个查询的HAVING或WHERE条件中。总结:如果第一个查询返回单个值(标量),我们可以直接在第二个查询的条件中使用子查询来嵌入第一个查询。示例代码:情况1:使用WHERE条件(当子查询返回单值)SELECT*FROMtable2WHEREcolumn2>(SELECTCOUNT(*)FROMtable1WHEREcondition);情况2:使用HAVING条件(当需要对分组进行过滤)SELECTcolumn,COUNT(*)FROMtable1GROUPBYcolumnHAVINGCOUNT(*)>(SELECTAVG(some_count)FROM...);注意事项:-子查询必须返回单个值(标量),否则会出错。-如果子查询可能返回多行,可以使用聚合函数(如MAX,MIN,AVG)将其转换为单值,或者使用IN、ANY等运算符。根据引用[2]:子查询的语法规则中提到“任何可以使用表达式的地方都可以使用子查询,只要它返回的是单个值”[^2]。因此,用户的问题可以通过在第二个查询的条件中嵌套一个返回单值的子查询(即第一条SQL)来解决。举例:需求:查询部门员工数量大于公司平均部门员工数量的部门。第一步:计算公司平均部门员工数量SELECTAVG(emp_count)FROM(SELECTdepartment_id,COUNT(*)ASemp_countFROMemployeesGROUPBYdepartment_id)t;第二步:查询哪些部门的员工数量大于这个平均值SELECTdepartment_id,COUNT(*)ASemp_countFROMemployeesGROUPBYdepartment_idHAVINGCOUNT(*)>(第一步的结果)合并成一条SQL:SELECTdepartment_id,COUNT(*)ASemp_countFROMemployeesGROUPBYdepartment_idHAVINGCOUNT(*)>(SELECTAVG(emp_count)FROM(SELECTCOUNT(*)ASemp_countFROMemployeesGROUPBYdepartment_id)t);注意:这里使用了两个子查询,内层子查询计算每个部门的员工数量,外层子查询计算这些数量的平均值,然后HAVING条件使用这个平均值。如果用户希望第一个查询返回的数量结果(比如一个具体的数字,例如10)作为第二个查询的条件,并且这个数字是事先计算好的,那么可以直接嵌入:SELECT*FROMtable2WHEREidIN(SELECTidFROMtable1GROUPBYidHAVINGCOUNT(*)>10);但这里的10是固定的。如果10是来自另一个查询的结果,则用子查询代替10。因此,核心思想:将第一条SQL(返回单值)作为子查询嵌入到第二条SQL条件中。如果第一条SQL返回多个值,而第二条查询需要用到多个值,则使用IN或EXISTS等。但用户明确要求是“数量结果”,即一个数值。根据引用[3]和[4],它们展示了在一条SQL中返回多个统计结果,但这不是我们这里的需求。我们这里的需求是将一个统计结果(数量)作为另一个查询的条件。另外,引用[1]提到用Python脚本整合多个数据库的查询结果,但用户的问题是关于在同一个数据库中使用SQL语句的,所以不适用。引用[5]是关于取第一条记录的,也不直接相关。所以,我们聚焦于子查询方法。结论:使用标量子查询(返回单个值的子查询)嵌入到主查询的WHERE或HAVING子句中。</think>### 将 SQL 查询结果数量作为另一查询条件的方法 在 SQL 中,可以通过 **子查询** 或 **变量存储** 的方式,将一条查询的结果数量作为另一条查询的条件。以下是具体实现方法: --- #### 方法 1:使用标量子查询(推荐) 当第一个查询返回**单个值**(如总数),直接在 WHERE/HAVING 子句中嵌套子查询: ```sql -- 示例:查询订单数超过平均值的客户 SELECT customer_id, customer_name FROM customers WHERE ( SELECT COUNT(*) FROM orders WHERE orders.customer_id = customers.customer_id ) > ( -- 子查询返回单值(平均订单数) SELECT AVG(order_count) FROM ( SELECT COUNT(*) AS order_count FROM orders GROUP BY customer_id ) t ); ``` **关键点**: 1. 子查询必须返回**单值**(标量子查询) 2. 嵌套在 WHERE/HAVING 条件中 3. 适用于聚合结果(COUNT/SUM/AVG 等)[^2] --- #### 方法 2:使用临表存储结果 当第一个查询返回**多个值**,通过临表存储结果: ```sql -- 步骤1: 将查询结果存入临表 CREATE TEMPORARY TABLE temp_counts AS SELECT product_id, COUNT(*) AS order_count FROM order_details GROUP BY product_id; -- 步骤2: 在第二个查询中使用临表 SELECT p.product_name, p.price FROM products p JOIN temp_counts tc ON p.product_id = tc.product_id WHERE tc.order_count > 100; -- 使用第一个查询的结果作为条件 ``` --- #### 方法 3:使用变量存储(MySQL) 在 MySQL 中可用用户变量存储中间结果: ```sql -- 存储第一个查询的结果到变量 SET @total_orders := (SELECT COUNT(*) FROM orders); -- 在第二个查询中使用变量 SELECT * FROM customers WHERE ( SELECT COUNT(*) FROM orders WHERE orders.customer_id = customers.customer_id ) > @total_orders * 0.1; -- 筛选订单数超过总量10%的客户 ``` --- #### ⚠️ 注意事项 1. **子查询返回类型**: - 单值用 `>`/`=` 等比较运算符 - 多值用 `IN` 或 `EXISTS` 2. **性能优化**: ```sql -- 添加 LIMIT 1 确保单值 WHERE value > (SELECT COUNT(*) FROM table WHERE ... LIMIT 1) ``` 3. **空值处理**: ```sql -- 使用 COALESCE 处理 NULL WHERE value > COALESCE((SELECT ...), 0) ``` 4. **关联子查询**:当子查询依赖外部值,需显式关联字段(如 `orders.customer_id = customers.customer_id`) > 通过合理使用子查询,可避免手动传递中间结果,实现高效的链式查询[^2][^4]。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值