SQL 中 Count 和Distinct的使用

本文介绍了如何使用SQL进行复杂的统计查询,特别是针对特定时间段内乘务员报单数量的统计,并展示了如何通过分页查询获取指定范围内的数据记录。

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

先来复习一下左连接:```
select * from tb_driverReportDetails
left join tb_driverReportInput on tb_driverReportInput.id=tb_driverReportDetails.reportid
left join tb_stationMileage on tb_stationMileage.id=mileageStationId

它的行数和select * from  tb_driverReportDetails  是一样的列数更多。
上述表中,tb_driverReportInput的一条对应tb_driverReportDetails的多条。
客户要求 统计出某个时间段内 乘务员报单数,就是tb_driverReportInput.id的个数。

首先要gorup by driverGh.
如果直接Count (tb_driverReportInput.id) 查出来的比较多,这是不对的, 改为count( distinct tb_driverReportInput.id)就可以了  。

完整的语句如下:


 ` select 
   (select gh from tb_driver where gh=driverGh) as  gh, 
   (select drivername from tb_driver where gh=driverGh) as  name, 
   (select department from tb_driver where gh=driverGh) as  department, 
   (select post from tb_driver where gh=driverGh) as  post, 
   '司机' as  workpost, 
    CAST(sum(actualOil) as decimal(18,2) ) as actualOil,
    CAST(sum(tb_driverReportDetails.comprehensiveOil) as decimal(18,2) ) as comprehensiveOil,
    CAST(sum(actualOil)-sum(tb_driverReportDetails.comprehensiveOil) as decimal(18,2) ) as saveOil,
	 0.5* sum(dzCount+dxCount+dcCount)+sum(score) as driverValue,
	  count( distinct tb_driverReportInput.id)  
    from  tb_driverReportDetails left join tb_driverReportInput on tb_driverReportInput.id=tb_driverReportDetails.reportid
	left join tb_stationMileage on tb_stationMileage.id=mileageStationId 
   where department='田集' and fromDateTime>@startdate and fromDateTime<@enddate  group by driverGh`


另外有个不重复的约束
首先,创建一张表table_a
CREATE TABLE [dbo].[table_a](
 [aID] [int] NULL,
 [aNum] [int] NULL
) ON [PRIMARY];

这个是没有unique约束的,若我们想给aID字段增加unique约束,则可有下列语句:
ALTER TABLE table_a ADD unique(aID);


-----------------修改完善,另一种写法-----------------
上面的太复杂,效率也不高,另外一种写法,是包一层,逻辑更清晰。

select
(select gh from tb_driver where gh=assistantDriverGh) as gh, (select drivername from tb_driver where gh=assistantDriverGh) as name,
(select department from tb_driver where gh=assistantDriverGh) as department,
(select post from tb_driver where gh=assistantDriverGh) as post,
‘副司机’ as workpost,
(select sum(driverOil) from tb_driverReportInput nb where nb.assistantDriverGh=b.assistantDriverGh)as SumDriverOil,

(select sum(driverOil)- SumComprehensiveOil from tb_driverReportInput nb where nb.assistantDriverGh=b.assistantDriverGh)as saveOil,

 * from 
(
 select assistantDriverGh, 0.5* sum(dzCount+dxCount+dcCount)+sum(score) as driverValue,
  count( distinct tb_driverReportInput.id) as  driverReportCount,
  sum(tb_driverReportDetails.comprehensiveOil)as SumComprehensiveOil  
from  tb_driverReportDetails left join tb_driverReportInput on tb_driverReportInput.id=tb_driverReportDetails.reportid
left join tb_stationMileage on tb_stationMileage.id=mileageStationId  

where (select department from tb_driver where tb_driver.gh=assistantDriverGh and post=‘副司机’)=‘谢桥’ group by assistantDriverGh
) b


分页查询语句:查询31-40条的数据

    select   top 10  *  from [Table] where Id not in (
    select   top 30  id from [Table]
    )  


<think>我们正在讨论SQL中的COUNT(DISTINCT)函数的使用方法注意事项。根据用户提供的引用内容,我们可以总结如下: 引用[1]提到DISTINCT可以与其他关键字如ORDER BY、WHEREGROUP BY结合使用,并给出了示例: ```sql SELECT DISTINCT NAME, age, score FROM students ORDER BY score DESC SELECT DISTINCT NAME, age, score FROM students GROUP BY NAME ``` 引用[2]详细说明了distinct的用法: - distinct用来查询不重复记录的条数,例如:`count(distinct id)` - distinct只能返回目标字段,无法返回其他字段 - distinct必须放在要查询字段的开头(即第一个参数) - 只能在SELECT语句中使用 - DISTINCT表示对后面所有参数的拼接取不重复的记录 - 不能与all同时使用(默认就是all,即全部记录) 引用[3]指出: - 在distinct语句中,select显示的字段只能是distinct指定的字段,其他字段不可能出现。例如,如果想获取distinct name以及对应的“备注”字段,直接通过distinct无法实现。 引用[4]是关于MySQLcount distinct null的注意事项: - 例如,以下语句产生两个计数:第一个是表中的行数,第二个是age列中非NULL值的数量: ```sql SELECT COUNT(*), COUNT(age) FROM table; ``` 现在,用户意图是获取关于COUNT(DISTINCT)函数的使用方法注意事项。 ### 回答结构: 1. **基本语法功能**:解释COUNT(DISTINCT)的作用基本用法。 2. **注意事项**:包括NULL值的处理、多列去重、性能等。 3. **示例**:给出几个典型示例。 4. **常见错误解决方法**:如引用中提到的限制如何规避。 5. **相关问题**:生成3个相关问题。 --- ### SQL COUNT(DISTINCT) 使用方法及注意事项 #### 1. 基本语法功能 `COUNT(DISTINCT expression)` 用于计算指定列或表达式中**唯一非空值**的数量。它是聚合函数,通常与`GROUP BY`子句一起使用,但也可以单独使用。 - **基本语法**: ```sql SELECT COUNT(DISTINCT column_name) FROM table_name; ``` - **功能**: - 对`column_name`列中的值进行去重(排除重复值)。 - 忽略`NULL`值(即不将`NULL`计入唯一值数量)。 - 返回一个整数,表示该列中不同非空值的数量。 #### 2. 注意事项 根据引用内容,结合数据库通用实践,需注意以下几点: ##### a) NULL值的处理 - `COUNT(DISTINCT column)` 会忽略`column`中的`NULL`值。例如,如果某列有5个值:`A, B, B, NULL, A`,则`COUNT(DISTINCT column)`返回2(即`A``B`)[^4]。 - 若需要包括`NULL`值作为计数项(即把`NULL`也视为一个类别),可改写为: ```sql SELECT COUNT(DISTINCT COALESCE(column_name, 'NULL_REPLACEMENT')) FROM table_name; ``` 但注意:这样会将`NULL`替换为特定字符串(如'NULL_REPLACEMENT'),然后计入计数。如果希望单独统计`NULL`,可结合条件聚合: ```sql SELECT COUNT(DISTINCT column_name) AS distinct_non_null, COUNT(DISTINCT CASE WHEN column_name IS NULL THEN 1 ELSE NULL END) AS distinct_null_count FROM table_name; ``` 注意:上述`distinct_null_count`实际上只会返回0或1,因为所有`NULL`都被视为相同。 ##### b) 多列去重 - `COUNT(DISTINCT ...)` 支持多列,会计算多列组合的唯一性。例如: ```sql SELECT COUNT(DISTINCT column1, column2) FROM table_name; ``` 这返回`(column1, column2)`组合的唯一数量(忽略其中任意列为`NULL`的组合)。 - 注意:在MySQL中,`COUNT(DISTINCT ...)`支持多列,但在某些数据库(如SQLite)中可能不支持多列去重计数。此时可用子查询: ```sql SELECT COUNT(*) FROM (SELECT DISTINCT column1, column2 FROM table_name) AS temp; ``` ##### c) 位置限制 - 在`SELECT`子句中,`DISTINCT`关键字必须紧跟在`SELECT`之后(如引用[2]所述)。但`COUNT(DISTINCT ...)`作为聚合函数,不受此限制影响,因为它本身就是函数的一部分。例如,以下写法正确: ```sql SELECT COUNT(DISTINCT name), AVG(age) FROM students; ``` ##### d) 与其他子句结合 - 与`GROUP BY`结合:按组计算唯一值数量。 ```sql SELECT class, COUNT(DISTINCT student_id) FROM enrollments GROUP BY class; ``` - 与`HAVING`结合:对聚合结果过滤。 ```sql SELECT class, COUNT(DISTINCT student_id) FROM enrollments GROUP BY class HAVING COUNT(DISTINCT student_id) > 10; ``` ##### e) 性能考虑 - `COUNT(DISTINCT ...)` 在大型数据集上可能较慢,因为它需要存储所有唯一值进行去重。 - 优化方法: - 使用近似计数(如Hive的`APPROX_COUNT_DISTINCT`或MySQL的`COUNT(DISTINCT ...)`结合索引)。 - 对查询列建立索引(特别是当列值基数高时)。 - 避免在大表上同时使用多个`COUNT(DISTINCT ...)`,可考虑分步计算。 #### 3. 示例 假设有表`students`: | id | name | age | class | |----|--------|-----|-------| | 1 | Alice | 20 | A | | 2 | Bob | 21 | A | | 3 | Alice | 20 | B | | 4 | NULL | 22 | B | | 5 | Bob | 21 | A | | 6 | Claire | 20 | B | **示例1:计算不同姓名的数量(忽略NULL)** ```sql SELECT COUNT(DISTINCT name) FROM students; ``` 结果:3(Alice, Bob, Claire;注意NULL被忽略) **示例2:按班级分组,计算每个班级的不同姓名数量** ```sql SELECT class, COUNT(DISTINCT name) FROM students GROUP BY class; ``` 结果: | class | COUNT(DISTINCT name) | |-------|----------------------| | A | 2 |(Alice, Bob) | B | 2 |(Alice, Claire;注意NULL被忽略) **示例3:计算(name, age)组合的唯一数量** ```sql SELECT COUNT(DISTINCT name, age) FROM students; ``` 结果:3((Alice,20), (Bob,21), (Claire,20)) #### 4. 常见错误及解决 - **错误1:尝试在`COUNT(DISTINCT ...)`中返回其他列** 如引用[3]指出,`SELECT DISTINCT`不能同时返回未去重的其他列。同样,`COUNT(DISTINCT ...)`仅返回聚合值,不能直接与其他非聚合列混用(除非用`GROUP BY`)。 **错误写法**: ```sql SELECT name, COUNT(DISTINCT name) FROM students; -- 错误!name未聚合 ``` **正确写法**: ```sql SELECT name, COUNT(DISTINCT name) OVER() FROM students; -- 使用窗口函数(非标准) -- 或分组 SELECT class, COUNT(DISTINCT name) FROM students GROUP BY class; ``` - **错误2:在`WHERE`子句中使用`DISTINCT`** `DISTINCT`只能用于`SELECT`语句(引用[2])。 **错误写法**: ```sql SELECT * FROM students WHERE DISTINCT name; -- 无效! ``` **替代方案**:使用`GROUP BY`或子查询。 - **错误3:忽略NULL导致计数偏差** 如需要统计包括`NULL`在内的唯一值,需额外处理(见上文NULL处理部分)。 #### 总结 `COUNT(DISTINCT expression)`是SQL中强大的聚合函数,用于计算唯一非空值的数量。使用时需注意NULL处理、多列组合、性能优化及语法限制。通过结合`GROUP BY`、`HAVING`等子句,可实现复杂的数据分析需求。 §§相关问题§§ 1. 如何在SQL中高效计算大数据集的近似唯一值数量? 2. SQLCOUNT(DISTINCT)与GROUP BY组合使用时有哪些性能陷阱? 3. 不同数据库(MySQL、Oracle、SQL Server)对COUNT(DISTINCT)的实现有何差异?</think>### SQL COUNT(DISTINCT) 使用方法及注意事项 #### 一、基本语法功能 `COUNT(DISTINCT expression)` 用于计算指定列或表达式中**唯一非空值**的数量: ```sql SELECT COUNT(DISTINCT column_name) FROM table_name; ``` - **功能**:统计列中不重复且非NULL的值的数量 - 支持单列或多列组合(部分数据库如Oracle需特殊处理多列情况) - 返回值:整数(不同值的计数) #### 二、核心注意事项 1. **NULL值处理**(关键!) - 自动忽略NULL值,只统计有效值 - 示例:列含 `[A, B, B, NULL]` → `COUNT(DISTINCT col)` 返回 `2` -
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值