SQL 语句中的 Seats Academy 计算
Posted
技术标签:
【中文标题】SQL 语句中的 Seats Academy 计算【英文标题】:Seats Academy calculation in SQL statement 【发布时间】:2021-10-31 02:49:38 【问题描述】:我的分配算法需要基于每个学院名额的剩余名额。
这是我的表格的插图:
tbl学院
Acad_id name numberOfSeats
------------------------------
1 A 2
2 B 2
3 C 1
4 D 5
5 E 3
tbl学生
stud_Id name `stud_purcentage` `stud_result` acad_id
----------------------------------------------------------
1 Alex 100 `Pass`
2 Lee 80.5 `Pass`
3 Lea 40.3 `Fail`
4 Loane 10 `Fail`
5 john 50 `Pass`
tblAcademy_selection
stud_id Acad_id order_preference
--------------------------------
1 1 1
1 3 2
4 3 1
4 2 2
4 4 3
我的算法:
SqlConnection dbcon = new SqlConnection(_conString);
SqlCommand scmd = new SqlCommand();
scmd.CommandText = "SELECT stud_Id,stud_fname,stud_purcentage,stud_totalMarks FROM tblStudent where stud_result='Pass' order by stud_purcentage Desc";
scmd.Connection = dbcon;
SqlDataAdapter da = new SqlDataAdapter(scmd);
DataTable dt = new DataTable();
dbcon.Open();
da.Fill(dt);
string[] array = new string[dt.Rows.Count];
// foreach (DataRow row in dt.Rows)
for (int a = 0; a < dt.Rows.Count; a++)
array[a] = dt.Rows[a]["stud_Id"].ToString();
SqlCommand scmd2 = new SqlCommand();
scmd2.CommandText = "select acad_Id,stud_Id from(SELECT tas.*, DENSE_RANK() OVER (PARTITION BY stud_id ORDER BY order_preference) AS row_id FROM tblAcademy ta JOIN tblAcademy_Selection tas ON ta.acad_Id = tas.acad_Id WHERE ta.numberOfSeats > 0 and stud_Id IN('" + array[a] + "')) DTL WHERE row_id = 1";
scmd2.Connection= dbcon;
SqlDataAdapter da2 = new SqlDataAdapter(scmd2);
DataTable dt2 = new DataTable();
da2.Fill(dt2);
string[] array2 = new string[dt2.Rows.Count];
string[] array3 = new string[dt2.Rows.Count];
for (int a2 = 0; a2 < dt2.Rows.Count; a2++)
String acad_Id = dt2.Rows[a2]["acad_Id"].ToString();
array2[a2] = dt2.Rows[a2]["stud_id"].ToString();
//string[,] array3 = new string[array2[a2],];
SqlCommand scmd3 = new SqlCommand();
scmd3.CommandText = "update tblStudent set acad_id='" + acad_Id + "' where stud_Id='" + array2[a2] + "'";
scmd3.Connection = dbcon;
scmd3.ExecuteNonQuery();
//ListBox1.Items.Add(array5);
getStudent();
在 scmd2
我的 sql 正在寻找一个静态列 numberOfSeats WHERE ta.numberOfSeats > 0
(学院配额),这不是我要寻找的。p>
我需要的是 where
条件基于计算 tblStudent 中每个 acadID 的总行数 - tblAcademy 中每个 acadID 的 numberOfSeat(学院配额)。
这里是获取剩余席位sql代码的代码:
SELECT distinct ta.acad_Id, numberOfSeats - Count(ts.acad_id) OVER (
PARTITION BY ta.acad_Id
) as remainingSeat
FROM tblAcademy ta,
tblStudent ts
where ta.acad_Id = ts.acad_Id or ts.acad_Id is null
我很难将smcd2 command text
的sql 代码定位到remainingSeat
别名而不是ta.numberOfSeats
【问题讨论】:
预期结果会有所帮助。并且 C# 块中的 SQL 代码包含顶部的表定义中不存在的列 我添加了更多关于我的算法和表格的信息 请描述您要实现的逻辑,非常不清楚。似乎您正试图根据order_preference
将Student
分配给Academy
,但不清楚您想如何做到这一点,例如,如果一个学院的学生太多会发生什么?整个算法很可能可以用 SQL 一次性完成
一个学生可以选择多个学院,这个选择记录在 tblAcademy_selection 但每个学生只能分配一个学院。当分配启动时,系统将必须选择通过的人并首先分配具有最佳百分比的人。根据学生在 tblAcademy_selection 中所做的选择,如果第一选择学院已满,则考虑第二选择,依此类推,如果他/她选择的所有学院都已满,则不会为他/她分配任何学院/她。
请修剪您的代码,以便更容易找到您的问题。请按照以下指南创建minimal reproducible example。
【参考方案1】:
看来你想多了。要查找剩余座位数,您只需要一个相关的子查询
SELECT
ta.acad_Id,
ta.numberOfSeats - ts.cn as remainingSeat
FROM tblAcademy ta
OUTER APPLY (
SELECT COUNT(*) AS cn
FROM tblStudent ts
WHERE ta.acad_Id = ts.acad_Id
) ts
WHERE ta.numberOfSeats - ts.total > 0;
-- or as a pre-grouped joined
SELECT
ta.acad_Id,
ta.numberOfSeats - ts.cn as remainingSeat
FROM tblAcademy ta
LEFT JOIN (
SELECT
ts.acad_Id,
COUNT(*) AS cn
FROM tblStudent ts
) ts ON ta.acad_Id = ts.acad_Id
WHERE ta.numberOfSeats - ts.cn;
目前尚不清楚您要对scmd2
中的查询执行什么操作
旁注:
始终参数化您的查询,不要向其中注入数据。 不要使用旧式,
交叉连接,它们在 30 年前已被弃用。
【讨论】:
非常感谢您的回答。 sql正在工作。我面临的问题是将我的 smcd2 命令文本中的 WHERE ta.numberOfSeats > 0 指向您发送给我的别名剩余座位。我的目标是查看如果剩余席位为 0,tblAcademy 中的 acadID 将不再接受学生并循环到 tblAcademy_Selection 中找到的学生第二选择。我需要每次在 tblStudent 中添加 acadID 时,所讨论的 acadID 都会减少 tblAcademy 中的座位数,这就是为什么我希望它指向您已完成的剩余座位别名。 好的,所以你可以把它放在APPLY
中,然后在WHERE
中引用它,已经编辑
请问我应该怎么写?我对 APPLY 感到困惑
啊抱歉我刚刚看到了,但是如何将这个 sql 语句与我在 scmd2 中完成的一个合并,因为这个 sql 只是计算剩余的座位并进行比较,如果它是大于 0。在 scmd2 中,它还按优先顺序检查每个学生的学院选择,以及那些通过并具有最佳百分比顺序的学生,按从好到坏的顺序排列,存储在数组 [a] 中,它是在 scmd 中完成的连接。
` select acad_Id,stud_Id from (SELECT ta.acad_Id, ta.numberOfSeats - ts.cn as remainingSeat,tas.*, DENSE_RANK() OVER (PARTITION BY stud_id ORDER BY order_preference) AS row_id FROM tblAcademy ta OUTER APPLY (SELECT COUNT(*) AS cn FROM tblStudent ts WHERE ta.acad_Id = ts.acad_Id) ts 加入 tblAcademy_Selection tas ON ta.acad_Id = tas.acad_Id WHERE ta.numberOfSeats - ts.cn > 0) dtl WHERE row_id = 1`.我试过这个,但我得到:'dtl' 的列'acad_Id' 被指定了多次。 ' 我完全被困住了。以上是关于SQL 语句中的 Seats Academy 计算的主要内容,如果未能解决你的问题,请参考以下文章
Portswigger-web-security-academy:sql injection