SQL Server中统计新抽奖序列与历史记录11-15位匹配次数
问题说明
窗体中有15个动态数组标签,每日生成1组1-25之间的15位随机数,保存到SQL Server的Result表中。需要将新生成的抽奖序列与约2500条历史记录对比,统计出匹配11位、12位、13位、14位、15位数字的记录数量(匹配少于11位无需统计),并将结果分别显示在5个Label控件的Text属性中。尝试过COUNT()和GROUP BY编写查询但未得到满意结果,寻求解决方案。
Result表结构及插入代码
表创建语句
CREATE TABLE [dbo].[Result]( [Concurso] [varchar](5) NOT NULL, [_01] [varchar](5) NOT NULL, [_02] [varchar](5) NOT NULL, [_03] [varchar](5) NOT NULL, [_04] [varchar](5) NOT NULL, [_05] [varchar](5) NOT NULL, [_06] [varchar](5) NOT NULL, [_07] [varchar](5) NOT NULL, [_08] [varchar](5) NOT NULL, [_09] [varchar](5) NOT NULL, [_10] [varchar](5) NOT NULL, [_11] [varchar](5) NOT NULL, [_12] [varchar](5) NOT NULL, [_13] [varchar](5) NOT NULL, [_14] [varchar](5) NOT NULL, [_15] [varchar](5) NOT NULL )
C#插入代码
cmd.CommandText = "insert into Result(Contest,_01,_02,_03,_04,_05,_06,_07,_08,_09,_10,_11,_12,_13,_14,_15)" + " Values(@Contest,@_01,@_02,@_03,@_04,@_05,@_06,@_07,@_08,@_09,@_10,@_11,@_12,@_13,@_14,@_15)"; cmd.Parameters.AddWithValue("@Contest", number.Contest); cmd.Parameters.AddWithValue("@_01", number.n_01.ToString("D2")); cmd.Parameters.AddWithValue("@_02", number.n_02.ToString("D2")); cmd.Parameters.AddWithValue("@_03", number.n_03.ToString("D2")); cmd.Parameters.AddWithValue("@_04", number.n_04.ToString("D2")); cmd.Parameters.AddWithValue("@_05", number.n_05.ToString("D2")); cmd.Parameters.AddWithValue("@_06", number.n_06.ToString("D2")); cmd.Parameters.AddWithValue("@_07", number.n_07.ToString("D2")); cmd.Parameters.AddWithValue("@_08", number.n_08.ToString("D2")); cmd.Parameters.AddWithValue("@_09", number.n_09.ToString("D2")); cmd.Parameters.AddWithValue("@_10", number.n_10.ToString("D2")); cmd.Parameters.AddWithValue("@_11", number.n_11.ToString("D2")); cmd.Parameters.AddWithValue("@_12", number.n_12.ToString("D2")); cmd.Parameters.AddWithValue("@_13", number.n_13.ToString("D2")); cmd.Parameters.AddWithValue("@_14", number.n_14.ToString("D2")); cmd.Parameters.AddWithValue("@_15", number.n_15.ToString("D2"));
解决方案
方法一:SQL端直接计算匹配数量并统计
核心思路是先计算每条历史记录与新序列的匹配数字个数,再按匹配数分组统计数量,过滤掉匹配数<11的记录。
假设新生成的序列数字分别为@v01到@v15(作为查询参数传入),SQL查询语句如下:
WITH MatchCounts AS ( SELECT -- 逐条计算对应位置的匹配数 CASE WHEN _01 = @v01 THEN 1 ELSE 0 END + CASE WHEN _02 = @v02 THEN 1 ELSE 0 END + CASE WHEN _03 = @v03 THEN 1 ELSE 0 END + CASE WHEN _04 = @v04 THEN 1 ELSE 0 END + CASE WHEN _05 = @v05 THEN 1 ELSE 0 END + CASE WHEN _06 = @v06 THEN 1 ELSE 0 END + CASE WHEN _07 = @v07 THEN 1 ELSE 0 END + CASE WHEN _08 = @v08 THEN 1 ELSE 0 END + CASE WHEN _09 = @v09 THEN 1 ELSE 0 END + CASE WHEN _10 = @v10 THEN 1 ELSE 0 END + CASE WHEN _11 = @v11 THEN 1 ELSE 0 END + CASE WHEN _12 = @v12 THEN 1 ELSE 0 END + CASE WHEN _13 = @v13 THEN 1 ELSE 0 END + CASE WHEN _14 = @v14 THEN 1 ELSE 0 END + CASE WHEN _15 = @v15 THEN 1 ELSE 0 END AS MatchNum FROM Result -- 排除刚插入的新记录(不需要则删除此条件) WHERE Concurso != @NewContest ) SELECT MatchNum, COUNT(*) AS RecordCount FROM MatchCounts WHERE MatchNum >= 11 GROUP BY MatchNum ORDER BY MatchNum DESC;
使用说明:
- 将新生成的15个数字和新记录的
Concurso值作为参数传入SQL命令。 - 查询结果会返回匹配数(11-15)及对应记录数量,无匹配的数字段不会返回,需在C#中默认赋值为0。
- 读取结果后直接赋值给对应Label控件,比如匹配15位的数量对应
Label15.Text。
方法二:C#端拉取数据后计算匹配数
如果SQL查询逻辑复杂,可在C#中拉取所有历史记录,逐条计算匹配数后统计:
// 新生成的序列(格式与数据库一致,如"01"、"05") string[] newNumbers = new string[] { "05", "12", "23", ... /* 共15个元素 */ }; // 拉取历史记录 List<string[]> historyRecords = new List<string[]>(); using (SqlConnection conn = new SqlConnection("你的数据库连接字符串")) { conn.Open(); string query = "SELECT _01,_02,_03,_04,_05,_06,_07,_08,_09,_10,_11,_12,_13,_14,_15 FROM Result WHERE Concurso != @NewContest"; using (SqlCommand cmd = new SqlCommand(query, conn)) { cmd.Parameters.AddWithValue("@NewContest", number.Contest); using (SqlDataReader reader = cmd.ExecuteReader()) { while (reader.Read()) { string[] record = new string[15]; for (int i = 0; i < 15; i++) { record[i] = reader.GetString(i); } historyRecords.Add(record); } } } } // 初始化统计字典 Dictionary<int, int> matchStats = new Dictionary<int, int>() { {11, 0}, {12, 0}, {13, 0}, {14, 0}, {15, 0} }; // 计算并统计匹配数 foreach (var record in historyRecords) { int matchCount = 0; for (int i = 0; i < 15; i++) { if (record[i] == newNumbers[i]) matchCount++; } if (matchCount >= 11) matchStats[matchCount]++; } // 赋值给Label控件 Label11.Text = matchStats[11].ToString(); Label12.Text = matchStats[12].ToString(); Label13.Text = matchStats[13].ToString(); Label14.Text = matchStats[14].ToString(); Label15.Text = matchStats[15].ToString();
注意事项
- 确保新生成数字的格式与数据库存储一致(如两位字符串),避免匹配错误。
- 若需求是数字集合匹配(不考虑位置),需修改匹配逻辑:将每条记录的数字存入HashSet,计算与新序列HashSet的交集数量即可。
内容的提问来源于stack exchange,提问作者Edilson Lemos
相关产品推荐
相关产品推荐

