如何用单条SQL查询同时统计老旧资产数、总数及占比?
单条SQL实现多维度资产统计(含老旧资产占比)
当然可以用单条SQL搞定!CASE语句刚好是解决这类分组统计需求的绝佳工具,完全不需要分开执行两次查询就能一次性算出老旧资产数、资产总数和占比三个指标。
完整SQL示例
SELECT o.OrganizationHierarchyUnitLevelThreeNm, o.OrganizationHierarchyUnitLevelTwoNm, -- 保留原查询的其他组织层级字段 o.OrganizationHierarchyUnitLevelOneNm, COUNT(*) AS total_assets, -- 统计每个组织的资产总数 SUM(CASE WHEN DATEDIFF(YEAR, a.PurchaseDate, GETDATE()) > 2 THEN 1 ELSE 0 END) AS old_assets_count, -- 筛选出使用年限超2年的老旧资产数 ROUND( CASE WHEN COUNT(*) = 0 THEN 0 ELSE SUM(CASE WHEN DATEDIFF(YEAR, a.PurchaseDate, GETDATE()) > 2 THEN 1 ELSE 0 END) * 1.0 / COUNT(*) END, 2 ) AS old_asset_ratio -- 计算老旧资产占比(保留两位小数) FROM Organizations o JOIN Assets a ON o.OrgId = a.OrgId -- 替换成你实际的关联表和关联字段 -- 移除原WHERE中的日期过滤条件,确保统计所有资产 GROUP BY o.OrganizationHierarchyUnitLevelThreeNm, o.OrganizationHierarchyUnitLevelTwoNm, o.OrganizationHierarchyUnitLevelOneNm ORDER BY o.OrganizationHierarchyUnitLevelThreeNm;
核心逻辑拆解
- CASE语句的妙用:在SUM函数里,CASE会给符合“使用年限超2年”的资产标记为1,不符合的标记为0,SUM后就得到了每个组织下的老旧资产总数,相当于把原查询的过滤逻辑嵌入到统计中。
- 总数统计:直接用
COUNT(*)就能拿到每个组织的全部资产数,因为我们已经移除了原WHERE的日期条件,不会过滤任何资产。 - 占比计算:用老旧资产数除以总数时,特意加了
*1.0把整数转成小数,避免出现整数除法导致的精度丢失;同时加了CASE判断总数为0的情况,防止触发除以0的错误,最后用ROUND保留两位小数让结果更直观。 - 分组保持一致:延续原查询的组织维度分组,确保统计结果完全按照你需要的组织层级聚合。
小细节调整提示
- 替换示例中的
PurchaseDate为你实际存储资产购买/启用日期的字段;GETDATE()是SQL Server的当前日期函数,MySQL用CURDATE(),Oracle用SYSDATE()。 - 确保关联表和关联字段(示例中的
OrgId)和你的数据库结构匹配。 - 如果要更精确地计算使用年限(比如按实际天数而非年份差),可以把条件改成
DATEDIFF(DAY, a.PurchaseDate, GETDATE()) > 730(两年约730天)。
内容的提问来源于stack exchange,提问作者Gargoyle
相关产品推荐
相关产品推荐

