sql 分组统计问题

simen_frankly 2014-12-07 09:40:10
比如说一个合同总金额为90万元,
A中标25万,B中标50万,C中标15万,现在首付款为30万,按比例各自比例分给A,B,C三人,如A得到25/90*30,三人都精确到元,SQL怎么实现啊?
...全文
137 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
simen_frankly 2014-12-08
  • 打赏
  • 举报
回复
学习了,感谢各位了!~~~~
还在加载中灬 2014-12-08
  • 打赏
  • 举报
回复
你到底是精确到元,还是万元? 还有,那种100元平分给3人的情况,如果要总额等于100,且精确到元的话,必须有一个是34块,两个33块的。 另外,你的测试数据没体现合同,如果有多个合同,需要区分不同的合同吗?
--第一次执行均摊
update T
set 实际付款=中标金额*1.0000/总中标金额*首付款
FROM(SELECT *,SUM(中标金额)OVER(PARTITION BY 总金额,首付款)[总中标金额] FROM 测试数据)T

--第二次执行将余数清除,确保等于总首付款
;WITH CTE AS(
	SELECT *,ROW_NUMBER()OVER(PARTITION BY 总金额,首付款 ORDER BY GETDATE())RN FROM 测试数据
)
update T1
set 实际付款=T2.首付款-T2.[总实际付款]
FROM CTE T1 JOIN
	(SELECT 总金额,首付款,SUM(实际付款)[总实际付款]
	FROM CTE
	WHERE RN>1
	GROUP BY 总金额,首付款
	)T2 ON T1.总金额=T2.总金额 AND T1.首付款=T2.首付款
WHERE T1.RN=1
Tiger_Zhao 2014-12-08
  • 打赏
  • 举报
回复
WITH test(总金额,中标方,中标金额,首付款,实际付款) AS (
SELECT 90,'A',25,30,Convert(int,NULL) UNION ALL
SELECT 90,'B',50,30,NULL UNION ALL
SELECT 90,'C',15,30,NULL
)
SELECT * INTO #temp FROM test

UPDATE #temp
SET 实际付款 = ROUND(首付款*中标金额/总金额,0)

SELECT 中标方,实际付款 FROM #temp

UPDATE TOP(1) #temp
SET 实际付款 = 实际付款 + 首付款 - (SELECT SUM(实际付款) FROM #temp)
WHERE 实际付款 = (SELECT MAX(实际付款) FROM #temp)

SELECT 中标方,实际付款 FROM #temp


(3 行受影响)

中标方 实际付款
------ -----------
A 8
B 16
C 5

(3 行受影响)

(1 行受影响)

中标方 实际付款
------ -----------
A 8
B 17
C 5

(3 行受影响)
skysenlin 2014-12-08
  • 打赏
  • 举报
回复
都说精英,学习
唐诗三百首 2014-12-07
  • 打赏
  • 举报
回复

create table 测试数据
(总金额 int,
 中标方 varchar(5),
 中标金额 int,
 首付款 int,
 实际付款 decimal(18,4)  -- 单位万,精确到元即为小数后4位.
)

insert into 测试数据
 select 90,'A',25,30,null union all
 select 90,'B',50,30,null union all
 select 90,'C',15,30,null


-- 计算实际付款
update 测试数据
 set 实际付款=中标金额*1.0000/总金额*首付款


-- 计算结果
select * from 测试数据
/*
总金额      中标方 中标金额    首付款      实际付款
----------- ----- ----------- ----------- ---------------------------------------
90          A      25          30          8.3333
90          B      50          30          16.6667
90          C      15          30          5.0000

(3 行受影响)
*/


-- 验证 三个和值是否等于首付款总数
select sum(实际付款) '首付款总数' from 测试数据
/*
首付款总数
---------------------------------------
30.0000

(1 行受影响)
*/
simen_frankly 2014-12-07
  • 打赏
  • 举报
回复
引用 1 楼 ky_min 的回复:
其实,你贴上测试数据,及期望结果 才能更清楚表达你的意思
;WITH 合同表(合同ID,名称,总金额,首总付)AS(
	SELECT 1,'合同',900000,300000
)
,中标情况表(合同ID,中标人,金额)AS(
	SELECT 1,'A',250000
	UNION ALL SELECT 1,'B',500000
	UNION ALL SELECT 1,'C',150000
)
--以上假设你数据是长那样的

--以下开始查询
SELECT T2.中标人,ROUND(CAST(T2.金额 AS DECIMAL(19,6))/T1.总金额*T1.首总付,0)均摊首付款 FROM 合同表 T1
	LEFT JOIN 中标情况表 T2 ON T1.合同ID=T2.合同ID
谢谢,结果已贴上了,round函数在不能整除的情况下,可能不对
simen_frankly 2014-12-07
  • 打赏
  • 举报
回复
使用round函数,在比例能整除的情况下没有问题,在比例不能整除的时候,三个和值不等于首付款总数 测试数据 总金额 中标方 中标金额 首付款 实际付款 90 A 25 30 8 90 B 50 30 17 90 C 15 30 5 实际付款列是我想要的结果
还在加载中灬 2014-12-07
  • 打赏
  • 举报
回复
其实,你贴上测试数据,及期望结果 才能更清楚表达你的意思
;WITH 合同表(合同ID,名称,总金额,首总付)AS(
	SELECT 1,'合同',900000,300000
)
,中标情况表(合同ID,中标人,金额)AS(
	SELECT 1,'A',250000
	UNION ALL SELECT 1,'B',500000
	UNION ALL SELECT 1,'C',150000
)
--以上假设你数据是长那样的

--以下开始查询
SELECT T2.中标人,ROUND(CAST(T2.金额 AS DECIMAL(19,6))/T1.总金额*T1.首总付,0)均摊首付款 FROM 合同表 T1
	LEFT JOIN 中标情况表 T2 ON T1.合同ID=T2.合同ID

22,209

社区成员

发帖
与我相关
我的任务
社区描述
MS-SQL Server 疑难问题
社区管理员
  • 疑难问题社区
  • 尘觉
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧