Sql Сервер: разделить набор данных при сохранении группировок строк - PullRequest
1 голос
/ 10 июля 2020

У меня есть запрос, который возвращает строки, сгруппированные по двум столбцам, например:

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

Я пытаюсь повысить производительность путем параллельной обработки набора результатов. Для этого мне нужно разделить результирующий набор на части примерно одинакового размера, при этом следя за тем, чтобы группировки строк не распределялись по более чем одному разделу, поскольку группировки важны для обработки. Это должно быть сделано с использованием нескольких запросов , а не одного запроса, а затем разделения результатов, потому что разделение строк после запроса данных влечет за собой слишком много накладных расходов (намерение состоит в том, чтобы назначить каждый запрос для SqlDataReader).

Обычно я использую ROW_NUMBER() для присвоения номеров строкам, а затем добавляю предложение WHERE к каждому запросу, аналогичному WHERE row_number > lowerbound AND row_number < upperbound, но это может привести к разделению набора данных в середине группировка.

Как я могу убедиться, что каждый запрос, который я использую, выбирает другой раздел данных, и каждая группировка в результате содержит все строки в группировке?

Я думал использовать DENSE_RANK() для назначить идентификатор каждой группе, но я не могу понять, как использовать это в сочетании с номерами строк для достижения желаемых результатов.

Идеальным результатом в этом примере был бы один запрос, который возвращает это:

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

И еще один запрос, который возвращает это:

Student_ID  Module_ID  Assignment_date  Assignment_grade
3           6          2013-03-02       B
3           6          2013-03-02       B

Ответы [ 2 ]

0 голосов
/ 10 июля 2020

Если вы хотите выделить группы студентов, вы можете использовать RANK() или DENSE_RANK():

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

или:

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

В чем разница между два? RANK() производит количество, соответствующее первому номеру строки каждой группы. DENSE_RANK() подсчитывается только по группам.

Итак, where number_r <= 3 будет извлекать все группы, включая группу с третьей строкой. В вашем случае это будут первые три строки.

Но where number_dr <= 3 получит первые три группы. В вашем случае он выберет все строки - и даже следующей группы нет в примере данных.

0 голосов
/ 10 июля 2020

Вы можете использовать функцию WINDOWS следующим образом:

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