sql server:在保留行分组的同时对数据集进行分区

djmepvbi  于 2021-07-24  发布在  Java
关注(0)|答案(2)|浏览(367)

我有一个查询,它返回按两列分组的行,如下所示:

  1. Student_ID Module_ID Assignment_date Assignment_grade
  2. 1 2 2010-01-01 C
  3. 1 2 2012-02-02 E
  4. 1 2 2013-03-02 A*
  5. 3 6 2013-03-02 B
  6. 3 6 2013-03-02 B

我试图通过并行处理结果集来提高性能。为此,我需要将结果集划分为大小接近相等的部分,同时确保行分组不会分布在多个分区中,因为分组对于处理非常重要。这必须使用多个查询来完成,而不是一个查询然后对结果进行分区,因为在查询数据之后对行进行分区会产生太多的开销(目的是将每个查询分配给一个 SqlDataReader ).
通常,我会用 ROW_NUMBER() 为行分配数字,然后向每个查询添加where子句,类似于 WHERE row_number > lowerbound AND row_number < upperbound 但这可能导致数据集在分组的中间被拆分。
如何确保使用的每个查询都选择不同的数据部分,并且结果中的每个分组都包含分组中的所有行?
我想用 DENSE_RANK() 为每个分组分配一个id,但我不知道如何将它与行号结合使用来实现我想要的结果。
本例中的理想结果是一个返回以下内容的查询:

  1. Student_ID Module_ID Assignment_date Assignment_grade
  2. 1 2 2010-01-01 C
  3. 1 2 2012-02-02 E
  4. 1 2 2013-03-02 A*

另一个查询返回:

  1. Student_ID Module_ID Assignment_date Assignment_grade
  2. 3 6 2013-03-02 B
  3. 3 6 2013-03-02 B
0vvn1miw

0vvn1miw1#

如果你想确定学生群体,你可以使用 RANK() 或者 DENSE_RANK() :

  1. select t.*, rank() over (order by student_id) as number_r
  2. from t;

或:

  1. select t.*, dense_rank() over (order by student_id) as number_dr
  2. from t;

两者有什么区别? RANK() 生成与每组的第一行号对应的计数。 DENSE_RANK() 只是按组计算。
所以, where number_r <= 3 将获取包含第三行的组的所有组。在您的情况下,这将是前三行。
但是 where number_dr <= 3 会把前三组人都找来。在您的示例中,它将选择所有行——甚至下一个组也不在数据示例中。

6vl6ewon

6vl6ewon2#

可以按如下方式使用windows功能:

  1. WITH CTE AS (SELECT T.*,
  2. COUNT(1) OVER () AS CNT,
  3. ROW_NUMBER() OVER (ORDER BY STUDENT_ID, MODULE_ID, ASSIGNMENT_DATE) AS RN,
  4. DENSE_RANK() OVER (ORDER BY STUDENT_ID, MODULE_ID) AS DR
  5. FROM YOUR_TABLE T)
  6. SELECT T1.*
  7. FROM CTE T
  8. -- WHERE DR <= (SELECT MAX(DR) FROM CTE T2 WHERE RN <= CEIL(CNT/2)) -- FIRST PART
  9. -- WHERE DR >= (SELECT MIN(DR) FROM CTE T2 WHERE RN > CEIL(CNT/2)) -- SECOND PART

相关问题