Классификация наборов записей на основе количества - PullRequest
1 голос
/ 09 октября 2019

У меня есть ученики, которые не учатся или поступают в другую школу, но зачислены в один или несколько классов или в наши классы по одному или нескольким предметам. Представление v_Enrollments возвращает полный список учащихся (NetId) и предмет (Subj) класса, который они посещают.

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

Я не владею оконными функциями и немного изо всех сил пытаюсь найти решение. Приведенный ниже запрос работает, но я не могу не задаться вопросом, есть ли лучшее решение.

select NetId, Subj
from (
    select NetId, Subj, RowNum
        , Max(RowNum) Over (partition by NetId) as MaxRowNum
    from (
        select NetId, Subj
            , Count(*) as Cnt
            , MAX(Count(*)) Over(partition by NetId) as MaxCnt
            , ROW_NUMBER() Over (partition by NetId order by checksum(NetId, Subj)) as RowNum
                                                    -- psuedorandom but repeatable ordering
        from v_Enrollment
        group by NetId, Subj
    ) as s2
    where Cnt = MaxCnt
) as s1
where RowNum = MaxRowNum
order by NetId

1 Ответ

1 голос
/ 10 октября 2019

Полагаю, нет необходимости в таком количестве операций. Это можно сделать примерно так:

WITH DataSource AS
(
    SELECT NetId
          ,Subj
          ,COUNT(*) AS CntClasses
    FROM v_Enrollment
    GROUP BY NetId
            ,Subj
), 
DataSourceOrdered AS
(
    SELECT NetId
          ,Subj
          ,ROW_NUMBER() OVER (ORDER BY CntClasses DESC, checksum(NetId, Subj)) AS [RowID]
    FROM DataSource
)
SELECT *
FROM DataSourceOrdered
WHERE [RowID] = 1
ORDER BY NetId;

Нам нужно знать количество классов для каждой пары студент-предмет. Затем используйте один ROW_NUMBER для заказа предметов по вашим условиям - подсчет старших классов, а затем ваше случайное число. После того, как это сделано, просто получите строки с [RowID] = 1.

...