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 &gt; 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_preferenceStudent 分配给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

如何计算sql中where语句中的行数?

SQL语句中的日期计算

在oracle中如何用sql语句计算一段时间中的星期六和星期天的天数?请大侠赐教!急求!!!!!!!!!!!

Seats

SQL查询语句是啥?