SQL 如何把去重计数 与 求和金额 放在一张表
时间: 2025-07-21 20:59:04 浏览: 6
<think>我们有一个需求:在一个SQL查询中同时执行去重计数和金额求和。根据引用[1]和[3],我们可以使用子查询或DISTINCT关键字来实现去重计数,同时使用SUM函数进行求和。引用[1]中的示例展示了一条SQL查询多个结果,其中使用了多个子查询分别计算不同的聚合值。
具体需求:假设我们有一个表(例如:BIZ_PROJECT_FINISHED),我们想要同时计算:
1. 某个字段的去重计数(例如:对COMPANY_NAME去重计数)
2. 另一个字段的求和(例如:对FUNDING_PLAN_SUM_TOTAL求和)
并且我们希望将这两个结果(可能还有其他的聚合结果)放在同一行中返回。
解决方案:我们可以使用多个子查询,每个子查询计算一个聚合值,然后将它们组合在一起。由于这些子查询都是基于同一个表,并且使用相同的条件(例如:相同的年份),我们可以将它们放在SELECT子句中作为不同的列。
示例:
引用[1]中的示例:
SELECT
(SELECT COUNT(ITEM_NAME) FROM BIZ_PROJECT_FINISHED WHERE PLAN_YEAR = #{year}) projectFinishedNameTotal,
(SELECT CONVERT(DECIMAL(18,0),(SUM(FUNDING_PLAN_SUM_TOTAL)/10000)) FROM BIZ_PROJECT_FINISHED WHERE PLAN_YEAR = #{year}) fundingPlanSumTotal,
(SELECT COUNT(DISTINCT COMPANY_NAME) FROM BIZ_PROJECT_FINISHED WHERE PLAN_YEAR = #{year}) companyNameTotal
但是,注意这种方式会多次扫描同一个表(每个子查询一次),如果数据量大可能效率不高。另一种方法是使用一个查询同时计算多个聚合值,例如使用条件聚合(CASE WHEN)或者使用GROUP BY然后使用JOIN,但这里因为我们需要的是全局的聚合(没有分组),所以我们可以考虑使用单次扫描并计算多个聚合值。
改进:我们可以将多个聚合函数放在同一个SELECT中,这样数据库可能只需要扫描一次表。例如:
SELECT
COUNT(ITEM_NAME) AS projectFinishedNameTotal,
CONVERT(DECIMAL(18,0), SUM(FUNDING_PLAN_SUM_TOTAL)/10000) AS fundingPlanSumTotal,
COUNT(DISTINCT COMPANY_NAME) AS companyNameTotal
FROM BIZ_PROJECT_FINISHED
WHERE PLAN_YEAR = #{year}
这样写只需要扫描一次表,效率更高。
因此,对于用户的问题,我们推荐使用第二种方式:在一个SELECT语句中同时使用多个聚合函数,包括COUNT(DISTINCT ...)和SUM(...)。
注意:COUNT(DISTINCT 字段) 用于计算该字段去重后的行数。SUM(字段) 用于对该字段求和。
但是,如果我们需要同时计算多个不同的去重计数(例如:对字段A去重计数,对字段B去重计数)以及多个不同的求和,那么我们可以直接在同一个SELECT语句中列出它们。
示例扩展:假设我们还需要对另一个字段(比如PROJECT_ID)进行去重计数,以及对另一个金额字段(比如ACTUAL_SPENDING)求和,我们可以这样写:
SELECT
COUNT(DISTINCT COMPANY_NAME) AS companyNameTotal,
COUNT(DISTINCT PROJECT_ID) AS projectIdTotal,
SUM(FUNDING_PLAN_SUM_TOTAL) AS totalFunding,
SUM(ACTUAL_SPENDING) AS totalSpending
FROM BIZ_PROJECT_FINISHED
WHERE PLAN_YEAR = #{year}
这样,我们就得到了一个包含多个去重计数和多个求和的结果行。
但是,需要注意的是,COUNT(DISTINCT) 在同一个SELECT语句中对多个字段使用时,每个COUNT(DISTINCT)都会独立计算,并且可能会增加查询的计算复杂度。不过,在大多数情况下,对于中等规模的数据集,这是可以接受的。
另外,引用[3]中提到,使用GROUP BY也可以实现去重,但是如果我们不需要分组,而是全局的聚合,那么使用COUNT(DISTINCT)更直接。
总结:在一个查询中同时执行去重计数和金额求和,我们可以使用一个SELECT语句,其中包含多个聚合函数(如COUNT(DISTINCT 字段)和SUM(字段)),并在WHERE子句中添加过滤条件。
因此,我们可以给出如下示例:
SELECT
COUNT(DISTINCT company_name) AS distinct_company_count,
SUM(funding_plan_sum_total) AS total_funding
FROM your_table
WHERE your_condition;
注意:这里假设表名为your_table,字段名根据实际情况替换,条件替换为your_condition。
如果用户需要将求和结果进行单位转换(如除以10000)并保留小数,可以使用CONVERT或CAST函数,也可以使用ROUND函数,具体取决于数据库系统。例如在SQL Server中:
SELECT
COUNT(DISTINCT company_name) AS distinct_company_count,
CONVERT(DECIMAL(18,2), SUM(funding_plan_sum_total)/10000.0) AS total_funding_in_ten_thousands
FROM your_table
WHERE your_condition;
或者使用ROUND函数:
SELECT
COUNT(DISTINCT company_name) AS distinct_company_count,
ROUND(SUM(funding_plan_sum_total)/10000.0, 2) AS total_funding_in_ten_thousands
FROM your_table
WHERE your_condition;
注意:在除法时使用10000.0(带小数点的数)可以避免整数除法截断小数部分。
根据引用[1]中使用了CONVERT(DECIMAL(18,0), ...),这里我们也可以根据需要调整小数位数(将0改为2表示保留两位小数)。
最后,根据用户的需求,我们还可以添加其他聚合计算。
因此,针对用户的问题,我们推荐使用上述方法。</think>在SQL中同时执行去重计数和金额求和,可以通过以下两种高效方式实现:
### 方法1:单次查询使用多个聚合函数(推荐)
```sql
SELECT
COUNT(DISTINCT company_name) AS distinct_company_count, -- 去重计数
SUM(funding_plan_sum_total) AS total_funding, -- 金额求和
CONVERT(DECIMAL(18,2), SUM(funding_plan_sum_total)/10000) AS total_funding_in_ten_thousands -- 金额转换并保留两位小数
FROM your_table
WHERE plan_year = 2023; -- 示例条件
```
**关键点解析**:
1. `COUNT(DISTINCT 字段)`
- 计算字段的唯一值数量(自动去重)[^3]
- 示例:`COUNT(DISTINCT company_name)` 统计不重复的公司数量
2. `SUM(字段)`
- 直接对数值字段求和(无需去重)[^5]
- 示例:`SUM(funding_plan_sum_total)` 累加所有资金计划总额
3. `CONVERT()` 数值转换
- 格式转换:`CONVERT(DECIMAL(18,2), 值)` 保留两位小数[^1]
- 单位转换:`SUM(...)/10000` 将结果转换为万元单位
---
### 方法2:子查询组合(复杂场景适用)
```sql
SELECT
(SELECT COUNT(DISTINCT company_name) FROM your_table WHERE plan_year=2023) AS company_count,
(SELECT SUM(funding_plan_sum_total) FROM your_table WHERE plan_year=2023) AS total_funding;
```
**适用场景**:
- 当不同聚合需要完全独立的过滤条件时
- 需注意:多次扫描表可能影响性能
---
### 注意事项
1. **去重范围**
`COUNT(DISTINCT)` 仅作用于指定字段,不同字段需分开计算[^3]
```sql
-- 同时计算两个字段的去重计数
COUNT(DISTINCT field1) AS cnt1,
COUNT(DISTINCT field2) AS cnt2
```
2. **性能优化**
- 确保`WHERE`条件字段有索引
- 单次查询聚合(方法1)比多个子查询(方法2)效率更高[^1]
3. **小数精度控制**
`CONVERT(DECIMAL(总位数,小数位数), 值)` 如:
```sql
CONVERT(DECIMAL(18,1), SUM(amount)) -- 保留1位小数
```
> 示例表结构参考:
> ```sql
> CREATE TABLE your_table (
> company_name VARCHAR(50),
> funding_plan_sum_total DECIMAL(18,2),
> plan_year INT
> );
> ```
阅读全文
相关推荐



















