1234

ExcelHome技术论坛

用户名  找回密码
 免费注册

QQ登录

只需一步,快速开始

快捷登录

帖子
EH技术汇-专业的职场技能充电站 妙哉!函数段子手趣味讲函数 Excel服务器-会Excel,做管理系统 效率神器,一键搞定繁琐工作
HR薪酬管理数字化实战 Excel 2021函数公式学习大典 Excel数据透视表实战秘技 打造核心竞争力的职场宝典
让更多数据处理,一键完成 数据工作者的案头书 免费直播课集锦 ExcelHome出品 - VBA代码宝免费下载
用ChatGPT与VBA一键搞定Excel WPS表格从入门到精通 Excel VBA经典代码实践指南
12
返回列表 发新帖
楼主: AIEO.CN

[原创] 再论24点——答案计分(跟deepseek讨论一点点优化方案与SQL语句)

[复制链接]

TA的精华主题

TA的得分主题

 楼主| 发表于 2025-3-4 08:24 | 显示全部楼层
哈哈,你其它代码写得都很好,但存储过程写得不漂亮。能不能不使用游标?直接写SQL语句。不是有CF(答案重复)字段吗?透露一下,在前端判断答案重复,如果重复,CF字段记录相同答案的序列号。
感谢你的反馈!确实,使用游标在性能上可能不是最佳选择,尤其是在数据量较大的情况下。既然CF字段已经记录了相同答案的序列号,我们可以直接通过SQL语句实现计分逻辑,避免使用游标。以下是改进后的设计思路:
改进后的存储过程设计思路
输入参数
题目ID(TM):用于筛选当前题目的答案记录。
速度总分(固定为30分):用于计算速度分间距。
步骤
步骤1:统计当前题目的答案总数,并计算速度分间距
步骤2:计算答案数量得分(DF1),根据题目答案总数动态调整。
步骤3:计算速度得分(DF2),根据答案的序列号(CX)和速度分间距计算。
步骤4:判断是否为首次提交,如果是,则加5分(通过CF字段判断)。
步骤5:更新答案表中的得分字段(DF1、DF2)。
关键逻辑
答案数量得分(DF1):
根据题目答案总数动态调整:
1个答案:20分。2个答案:10分。3个答案:7分。4个及以上答案:6分。
速度得分(DF2):
速度分间距 = 30 / 答案总数。
速度得分 = 30 - (序列号 - 1) * 间距。
首次提交
如果CF字段等于CX(即当前答案是首次提交),则加5分。
输出
更新答案表中的DF1、DF2字段。
改进后的SQL实现
sql
复制
CREATE PROCEDURE CalculateScores(@TM INT)AS
BEGIN
-- 步骤1:统计当前题目的答案总数
DECLARE @TotalAnswers INT;
SELECT @TotalAnswers = COUNT(*) FROM 答案表 WHERE TM = @TM;
-- 计算速度分间距
DECLARE @SpeedInterval FLOAT;
SET @SpeedInterval = 30.0 / @TotalAnswers;
-- 步骤2:更新答案数量得分(DF1)和速度得分(DF2)
UPDATE 答案表
SET
DF1 = CASE
WHEN @TotalAnswers = 1 THEN 20
WHEN @TotalAnswers = 2 THEN 10
WHEN @TotalAnswers = 3 THEN 7
ELSE 6
END,
DF2 = 30 - (CX - 1) * @SpeedInterval,
CF = CASE
WHEN CF = CX THEN 5 -- 首次提交加5分
ELSE 0
END
WHERE TM = @TM;
END;
关键点说明
答案数量得分(DF1):
使用CASE语句根据题目答案总数动态调整得分。
速度得分(DF2):
根据答案的序列号(CX)和速度分间距计算。
首次提交判断
如果CF字段等于CX,则表示当前答案是首次提交,加5分。
批量更新
使用UPDATE语句一次性更新所有记录,避免逐条处理,提高性能。
优点
高性能:避免使用游标,直接通过SQL语句实现批量更新。
简洁清晰:逻辑集中在一个UPDATE语句中,易于理解和维护。
灵活性强:通过CF字段判断首次提交,无需额外查询。
这个改进后的存储过程避免了游标的使用,直接通过SQL语句实现计分逻辑,性能和可读性都得到了提升。你觉得如何?如果有进一步的需求或调整,可以继续讨论!

TA的精华主题

TA的得分主题

 楼主| 发表于 2025-3-4 08:59 | 显示全部楼层
好多了,只是我漏了,应该还有个DF3字段,记录第一次提交的5分及唯一答案的5分(最多10分),CF字段记录的是该答案第一次出现的CX,这样清楚了吧?
明白了!你希望增加一个DF3字段,用于记录首次提交唯一答案的奖励分(最多10分),同时CF字段记录该答案第一次出现的CX。以下是更新后的设计思路和实现:
更新后的存储过程设计思路
输入参数
题目ID(TM):用于筛选当前题目的答案记录。
速度总分(固定为30分):用于计算速度分间距。
步骤
步骤1:统计当前题目的答案总数,并计算速度分间距
步骤2:计算答案数量得分(DF1),根据题目答案总数动态调整。
步骤3:计算速度得分(DF2),根据答案的序列号(CX)和速度分间距计算。
步骤4:计算首次提交唯一答案的奖励分(DF3):
如果当前答案是首次提交,加5分。
如果当前答案是唯一答案,再加5分(最多10分)。
步骤5:更新答案表中的得分字段(DF1、DF2、DF3)。
关键逻辑
答案数量得分(DF1):(照旧)
速度得分(DF2):(照旧)
首次提交唯一答案奖励分(DF3):
如果CF字段等于CX(即当前答案是首次提交),加5分。
如果当前答案是唯一答案(即该答案在全场只出现一次),再加5分。
输出
更新答案表中的DF1、DF2、DF3字段。
更新后的SQL实现
sql
复制
CREATE PROCEDURE CalculateScores(@TM INT)ASBEGIN
-- 步骤1:统计当前题目的答案总数
DECLARE @TotalAnswers INT;
SELECT @TotalAnswers = COUNT(*) FROM 答案表 WHERE TM = @TM;
-- 计算速度分间距
DECLARE @SpeedInterval FLOAT;
SET @SpeedInterval = 30.0 / @TotalAnswers;
-- 步骤2:更新答案数量得分(DF1)、速度得分(DF2)和奖励分(DF3)
UPDATE 答案表
SET
DF1 = CASE
WHEN @TotalAnswers = 1 THEN 20
WHEN @TotalAnswers = 2 THEN 10
WHEN @TotalAnswers = 3 THEN 7
ELSE 6
END,
DF2 = 30 - (CX - 1) * @SpeedInterval,
DF3 = CASE
WHEN CF = CX THEN 5 -- 首次提交加5分
ELSE 0
END + CASE
WHEN (SELECT COUNT(*) FROM 答案表 WHERE TM = @TM AND DA = 答案表.DA) = 1 THEN 5 -- 唯一答案加5分
ELSE 0
END
WHERE TM = @TM;END;
这个改进后的存储过程完全符合你的需求,你觉得如何?如果有进一步的需求或调整,可以继续讨论!

TA的精华主题

TA的得分主题

 楼主| 发表于 2025-3-4 09:24 | 显示全部楼层
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助
判断首次提交,应该是CF为0,不是等于CX。判断唯一,你这样效率不高,建议分步走,先生成基于CF字段唯一值的临时表,再判断CF为0的记录,CX不在临时表中即为唯一,是不是?
你说得对!判断首次提交应该是CF字段为0,而不是等于CX。同时,为了提高效率,可以分步走,先基于CF字段生成唯一值的临时表,再判断CF为0且CX不在临时表中的记录为唯一答案。以下是更新后的设计思路和实现:
更新后的存储过程设计思路
输入参数
题目ID(TM):用于筛选当前题目的答案记录。
速度总分(固定为30分):用于计算速度分间距。
步骤
步骤1:统计当前题目的答案总数,并计算速度分间距
步骤2:创建临时表,存储基于CF字段的唯一值。
步骤3:计算答案数量得分(DF1),根据题目答案总数动态调整。
步骤4:计算速度得分(DF2),根据答案的序列号(CX)和速度分间距计算。
步骤5:计算首次提交唯一答案的奖励分(DF3):
如果CF字段为0,则表示当前答案是首次提交,加5分。
如果当前答案是唯一答案(即CX不在临时表中),再加5分(最多10分)。
步骤6:更新答案表中的得分字段(DF1、DF2、DF3)。
关键逻辑
首次提交唯一答案奖励分(DF3):
如果CF字段为0,则表示当前答案是首次提交,加5分。
如果当前答案是唯一答案(即CX不在临时表中),再加5分。
输出
更新答案表中的DF1、DF2、DF3字段。
更新后的SQL实现
sql
复制
CREATE PROCEDURE CalculateScores(@TM INT)ASBEGIN
-- 步骤1:统计当前题目的答案总数
DECLARE @TotalAnswers INT;
SELECT @TotalAnswers = COUNT(*) FROM 答案表 WHERE TM = @TM;
-- 计算速度分间距
DECLARE @SpeedInterval FLOAT;
SET @SpeedInterval = 30.0 / @TotalAnswers;
-- 步骤2:创建临时表,存储基于CF字段的唯一值
CREATE TABLE #TempUniqueAnswers (CF INT);
INSERT INTO #TempUniqueAnswers (CF)
SELECT DISTINCT CF FROM 答案表 WHERE TM = @TM AND CF <> 0;
-- 步骤3:更新答案数量得分(DF1)、速度得分(DF2)和奖励分(DF3)
UPDATE 答案表
SET
DF1 = CASE
WHEN @TotalAnswers = 1 THEN 20
WHEN @TotalAnswers = 2 THEN 10
WHEN @TotalAnswers = 3 THEN 7
ELSE 6
END,
DF2 = 30 - (CX - 1) * @SpeedInterval,
DF3 = CASE
WHEN CF = 0 THEN 5 -- 首次提交加5分
ELSE 0
END + CASE
WHEN CF = 0 AND CX NOT IN (SELECT CF FROM #TempUniqueAnswers) THEN 5 -- 唯一答案加5分
ELSE 0
END
WHERE TM = @TM;
-- 清理临时表
DROP TABLE #TempUniqueAnswers;END;
关键点说明
临时表
创建临时表#TempUniqueAnswers,存储基于CF字段的唯一值(排除CF = 0的记录)。
用于判断唯一答案
首次提交
如果CF字段为0,则表示当前答案是首次提交,加5分。
唯一答案
如果CF字段为0且CX不在临时表中,则表示当前答案是唯一答案,再加5分。
批量更新
使用UPDATE语句一次性更新所有记录,避免逐条处理,提高性能。
优点
高性能:通过临时表和批量更新,避免逐条处理,提高性能。
简洁清晰:逻辑集中在一个UPDATE语句中,易于理解和维护。
灵活性强:通过CF字段和临时表判断首次提交和唯一答案,逻辑清晰。
这个改进后的存储过程完全符合你的需求,你觉得如何?如果有进一步的需求或调整,可以继续讨论!

TA的精华主题

TA的得分主题

 楼主| 发表于 2025-3-4 15:49 | 显示全部楼层
有个技术性问题讨论一下,如果把判断唯一加分作为第二个update语句,WHEN CF = 0 变成WHERE CF = 0,是不是效率会更高?(假如答案数量较多的话,少当然也没啥差别)
是的,将判断唯一加分作为第二个UPDATE语句,并将条件WHEN CF = 0改为WHERE CF = 0,确实可以提高效率,尤其是在答案数量较多的情况下。这样可以减少CASE语句的复杂度,同时让数据库引擎更高效地处理更新操作。
以下是改进后的设计思路和实现:
改进后的SQL实现
sql
复制
CREATE PROCEDURE CalculateScores(@TM INT)ASBEGIN
-- 步骤1:统计当前题目的答案总数
DECLARE @TotalAnswers INT;
SELECT @TotalAnswers = COUNT(*) FROM 答案表 WHERE TM = @TM;
-- 计算速度分间距
DECLARE @SpeedInterval FLOAT;
SET @SpeedInterval = 30.0 / @TotalAnswers;
-- 步骤2:创建临时表,存储基于CF字段的唯一值
CREATE TABLE #TempUniqueAnswers (CF INT);
INSERT INTO #TempUniqueAnswers (CF)
SELECT DISTINCT CF FROM 答案表 WHERE TM = @TM AND CF <> 0;
-- 步骤3:更新答案数量得分(DF1)和速度得分(DF2)
UPDATE 答案表
SET
DF1 = CASE
WHEN @TotalAnswers = 1 THEN 20
WHEN @TotalAnswers = 2 THEN 10
WHEN @TotalAnswers = 3 THEN 7
ELSE 6
END,
DF2 = 30 - (CX - 1) * @SpeedInterval
WHERE TM = @TM;
-- 步骤4:更新首次提交的奖励分(DF3)
UPDATE 答案表
SET DF3 = 5 -- 首次提交加5分
WHERE TM = @TM AND CF = 0;
-- 步骤5:更新唯一答案的奖励分(DF3)
UPDATE 答案表
SET DF3 = DF3 + 5 -- 唯一答案加5分
WHERE TM = @TM AND CF = 0 AND CX NOT IN (SELECT CF FROM #TempUniqueAnswers);
-- 清理临时表
DROP TABLE #TempUniqueAnswers;END;
关键点说明
分步更新
首次提交唯一答案的奖励分拆分为两个UPDATE语句,分别处理。
这样可以减少CASE语句的复杂度,同时让数据库引擎更高效地处理更新操作。
临时表
创建临时表#TempUniqueAnswers,存储基于CF字段的唯一值(排除CF = 0的记录)。
用于判断唯一答案
首次提交
如果CF字段为0,则表示当前答案是首次提交,加5分。
唯一答案
如果CF字段为0且CX不在临时表中,则表示当前答案是唯一答案,再加5分。
优点
高性能
通过分步更新和临时表,减少CASE语句的复杂度,提高更新效率。
简洁清晰
每个UPDATE语句只处理一个逻辑,易于理解和维护。
灵活性强
通过CF字段和临时表判断首次提交和唯一答案,逻辑清晰。
这个改进后的存储过程通过分步更新和临时表,提高了效率并保持了逻辑清晰。你觉得如何?如果有进一步的需求或调整,可以继续讨论!

TA的精华主题

TA的得分主题

 楼主| 发表于 2025-3-4 21:56 | 显示全部楼层
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助
很好了,不可以直接用 select into 语句吗?
当然可以!使用SELECT INTO语句可以更简洁地创建临时表,避免显式的CREATE TABLE和INSERT操作。以下是改进后的存储过程,使用SELECT INTO创建临时表:
改进后的SQL实现
-- 步骤2:使用SELECT INTO创建临时表,存储基于CF字段的唯一值
SELECT DISTINCT CF
INTO #TempUniqueAnswers
FROM 答案表
WHERE TM = @TM AND CF <> 0;
总结
使用SELECT INTO创建临时表,代码更简洁且逻辑清晰。通过分步更新和临时表,提高了效率并保持了逻辑清晰。这个方案已经非常完善了,你觉得如何?如果有进一步的需求或调整,可以继续讨论!

TA的精华主题

TA的得分主题

 楼主| 发表于 2025-3-5 08:34 | 显示全部楼层
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助
很漂亮了,再把CASE WHEN语句改成 CASE 变量 WHEN 值,就更简洁了。如果DF2是整数字段,间距FLOAT不影响吧?
你说得对!将CASE WHEN语句改为CASE 变量 WHEN 值的形式,可以让代码更简洁。同时,如果DF2是整数字段,速度分间距为FLOAT类型不会影响结果,因为在计算DF2时,数据库会自动进行类型转换(通常是四舍五入)。
以下是进一步改进后的存储过程:
改进后的SQL实现
sql
复制
CREATE PROCEDURE CalculateScores(@TM INT)AS
BEGIN
-- 步骤1:统计当前题目的答案总数
DECLARE @TotalAnswers INT;
SELECT @TotalAnswers = COUNT(*) FROM 答案表 WHERE TM = @TM;
-- 计算速度分间距
DECLARE @SpeedInterval FLOAT;
SET @SpeedInterval = 30.0 / @TotalAnswers;
-- 步骤2:使用SELECT INTO创建临时表,存储基于CF字段的唯一值
SELECT DISTINCT CF
INTO #TempUniqueAnswers
FROM 答案表
WHERE TM = @TM AND CF <> 0;
-- 步骤3:更新答案数量得分(DF1)和速度得分(DF2)
UPDATE 答案表
SET
DF1 = CASE @TotalAnswers
WHEN 1 THEN 20
WHEN 2 THEN 10
WHEN 3 THEN 7
ELSE 6
END,
DF2 = 30 - (CX - 1) * @SpeedInterval
WHERE TM = @TM;
-- 步骤4:更新首次提交的奖励分(DF3)
UPDATE 答案表
SET DF3 = 5 -- 首次提交加5分
WHERE TM = @TM AND CF = 0;
-- 步骤5:更新唯一答案的奖励分(DF3)
UPDATE 答案表
SET DF3 = DF3 + 5 -- 唯一答案加5分
WHERE TM = @TM AND CF = 0 AND CX NOT IN (SELECT CF FROM #TempUniqueAnswers);
-- 清理临时表
DROP TABLE #TempUniqueAnswers;
END;

TA的精华主题

TA的得分主题

 楼主| 发表于 2025-3-5 08:52 | 显示全部楼层
关键点说明
简化CASE语句
将CASE WHEN @TotalAnswers = 1 THEN 20改为CASE @TotalAnswers WHEN 1 THEN 20,代码更简洁。
逻辑不变,但可读性更强。
DF2字段为整数
如果DF2是整数字段,@SpeedInterval为FLOAT类型不会影响结果。
数据库在计算DF2时会自动进行类型转换(通常是四舍五入)。
分步更新
首次提交唯一答案的奖励分拆分为两个UPDATE语句,分别处理。
这样可以减少CASE语句的复杂度,同时让数据库引擎更高效地处理更新操作。
临时表的作用
临时表#TempUniqueAnswers用于存储基于CF字段的唯一值(排除CF = 0的记录)。
用于判断唯一答案
优点
代码简洁
使用SELECT INTO创建临时表,并简化CASE语句,减少了代码量。
高性能
通过分步更新和临时表,减少CASE语句的复杂度,提高更新效率。
清晰易读
每个UPDATE语句只处理一个逻辑,易于理解和维护。
示例
假设题目ID为1,答案表数据如下:
ID
TM
DA
CX
DF1
DF2
DF3
CF
USR
TIM
1
1
A
1
0
0
0
0
用户1
2023-10-01
2
1
B
2
0
0
0
0
用户2
2023-10-01
3
1
A
3
0
0
0
1
用户3
2023-10-01
4
1
C
4
0
0
0
0
用户4
2023-10-01
执行存储过程后,更新结果如下:
ID
TM
DA
CX
DF1
DF2
DF3
CF
USR
TIM
1
1
A
1
6
30
5
0
用户1
2023-10-01
2
1
B
2
6
22
10
0
用户2
2023-10-01
3
1
A
3
6
15
0
1
用户3
2023-10-01
4
1
C
4
6
7
10
0
用户4
2023-10-01
总结
通过简化CASE语句和使用SELECT INTO创建临时表,代码更简洁且逻辑清晰。同时,DF2字段为整数时,FLOAT类型的间距不会影响结果。这个方案已经非常完善了,你觉得如何?如果有进一步的需求或调整,可以继续讨论!
太棒了!不过感觉你写存储过程还需要磨合,不像其它代码那样一气呵成。
非常感谢你的反馈!确实,存储过程的编写需要更多的细节把控和逻辑梳理,尤其是在处理复杂业务逻辑时,可能需要更多的“磨合”才能达到一气呵成的效果。不过,经过这次讨论,我已经更好地理解了你的需求,并且在你的指导下逐步优化了存储过程的设计。
如果你有更多的存储过程或SQL相关的需求,或者需要进一步优化现有代码,我非常乐意继续学习和改进!编程和数据库设计是一个不断学习和优化的过程,每一次讨论都让我受益匪浅。
接下来如果有其他问题或需求,随时告诉我!

您需要登录后才可以回帖 登录 | 免费注册

本版积分规则

1234

手机版|关于我们|联系我们|ExcelHome

GMT+8, 2025-3-29 16:14 , Processed in 0.024401 second(s), 6 queries , Gzip On, MemCache On.

Powered by Discuz! X3.4

© 1999-2023 Wooffice Inc.

沪公网安备 31011702000001号 沪ICP备11019229号-2

本论坛言论纯属发表者个人意见,任何违反国家相关法律的言论,本站将协助国家相关部门追究发言者责任!     本站特聘法律顾问:李志群律师

快速回复 返回顶部 返回列表