4

Я не могу на всю жизнь понять, как получить взвешенное ранжирование по десяткам по категориям. Например, студент должен ответить на 10 вопросов по трем категориям (как в случае вопросов, так и в # категории будет изменяться в конце концов). Чтобы получить общий балл, верхний 1 балл в каждой из категорий X (3) будет добавлен к тому, что осталось, чтобы добавить до 10 полных баллов.Требуется ли это рекурсивный CTE, просто творческие функции окна, цикл?

Вот данные. Я использовал случай, когда row_number(), чтобы получить TopInCat

http://sqlfiddle.com/#!6/e6e9f/1

скрипку имеет больше студентов.

 
| Question | Student | Category | Score | TopInCat | 
|----------|---------|----------|-------|----------| 
| 120149 |  125 |  6 | 1  |  1 | 
| 120127 |  125 |  6 | 0.9 |  0 | 
| 120124 |  125 |  6 | 0.8 |  0 | 
| 120125 |  125 |  6 | 0.7 |  0 | 
| 120130 |  125 |  6 | 0.6 |  0 | 
| 120166 |  125 |  6 | 0.5 |  0 | 
| 120161 |  125 |  6 | 0.4 |  0 | 
| 120138 |  125 |  4 | 0.15 |  1 | 
| 120069 |  125 |  4 | 0.15 |  0 | 
| 120022 |  125 |  4 | 0.15 |  0 | 
| 120002 |  125 |  4 | 0.15 |  0 | 
| 120068 |  125 |  2 | 0.01 |  1 | 
| 120050 |  125 |  3 | 0.05 |  1 | 
| 120139 |  125 |  2 | 0  |  0 | 
| 120156 |  125 |  2 | 0  |  0 | 

Это то, как я предполагаю, что он должен выглядеть, но это не обязательно должно быть именно это. Мне просто нужно иметь 10 вопросов по 3 деталям данных таким образом, чтобы я мог суммировать и усреднять столбцы Sort 1-10 ниже. 999-е могут быть нулевыми или любыми, если я могу судить о том, что важно и представить детали.

 
| Question | Student | Category | Score | TopInCat | Sort | 
|----------|---------|----------|-------|----------|------| 
| 120149 |  125 |  6 | 1  |  1 | 1 | 
| 120138 |  125 |  4 | 0.15 |  1 | 2 | 
| 120068 |  125 |  2 | 0.01 |  1 | 3 | 
| 120127 |  125 |  6 | 0.9 |  0 | 4 | 
| 120124 |  125 |  6 | 0.8 |  0 | 5 | 
| 120125 |  125 |  6 | 0.7 |  0 | 6 | 
| 120130 |  125 |  6 | 0.6 |  0 | 7 | 
| 120166 |  125 |  6 | 0.5 |  0 | 8 | 
| 120161 |  125 |  6 | 0.4 |  0 | 9 | 
| 120069 |  125 |  4 | 0.15 |  0 | 10 | 
| 120022 |  125 |  4 | 0.15 |  0 | 999 | 
| 120002 |  125 |  4 | 0.15 |  0 | 999 | 
| 120050 |  125 |  3 | 0.05 |  1 | 999 | 
| 120139 |  125 |  2 | 0  |  0 | 999 | 
| 120156 |  125 |  2 | 0  |  0 | 999 | 

Последнее, что категория не имеет значения, когда порог X (3) встречается. Таким образом, 4-я категория будет нормально сортироваться.

 
| Question | Student | Category | Score | TopInCat | Sort | 
|----------|---------|----------|-------|----------|------| 
| 120149 |  126 |  6 | 1  |  1 | 1 | 
| 120138 |  126 |  4 | 0.75 |  1 | 2 | 
| 120068 |  126 |  2 | 0.50 |  1 | 3 | 
| 120127 |  126 |  6 | 0.9 |  0 | 4 | 
| 120124 |  126 |  6 | 0.8 |  0 | 5 | 
| 120125 |  126 |  6 | 0.7 |  0 | 6 | 
| 120130 |  126 |  6 | 0.6 |  0 | 7 | 
| 120166 |  126 |  6 | 0.5 |  0 | 8 | 
| 120050 |  126 |  3 | 0.45 |  1 | 9 |******** 
| 120161 |  126 |  6 | 0.4 |  0 | 10 | 
| 120069 |  126 |  4 | 0.15 |  0 | 999 | 
| 120022 |  126 |  4 | 0.15 |  0 | 999 | 
| 120002 |  126 |  4 | 0.15 |  0 | 999 | 
| 120139 |  126 |  2 | 0  |  0 | 999 | 
| 120156 |  126 |  2 | 0  |  0 | 999 | 

Я очень ценю любую помощь. Я бил головой об этом несколько дней.

ответ

2

С такими вопросами я хотел бы продолжить подход «строительных блоков». Следуя принципу , сначала сделайте это, тогда , если вам нужно сделать это быстро, этого первого шага достаточно часто.

Таким образом, учитывая

CREATE TABLE WeightedScores 
    ([Question] int, [Student] int, [Category] int, [Score] dec(3,2)) 
; 

и ваши выборочные данные

INSERT INTO WeightedScores 
    ([Question], [Student], [Category], [Score]) 
VALUES 
    (120161, 123, 6, 1), (120166, 123, 6, 0.64), (120138, 123, 4, 0.57), (120069, 123, 4, 0.5), 
    (120068, 123, 2, 0.33), (120022, 123, 4, 0.18), (120061, 123, 6, 0), (120002, 123, 4, 0), 
    (120124, 123, 6, 0), (120125, 123, 6, 0), (120137, 123, 6, 0), (120154, 123, 6, 0), 
    (120155, 123, 6, 0), (120156, 123, 6, 0), (120139, 124, 2, 1), (120156, 124, 2, 1), 
    (120050, 124, 3, 0.88), (120068, 124, 2, 0.87), (120161, 124, 6, 0.87), (120138, 124, 4, 0.85), 
    (120069, 124, 4, 0.51), (120166, 124, 6, 0.5), (120022, 124, 4, 0.43), (120002, 124, 4, 0), 
    (120130, 124, 6, 0), (120125, 124, 6, 0), (120124, 124, 6, 0), (120127, 124, 6, 0), 
    (120149, 124, 6, 0), (120149, 125, 6, 1), (120127, 125, 6, 0.9), (120124, 125, 6, 0.8), 
    (120125, 125, 6, 0.7), (120130, 125, 6, 0.6), (120166, 125, 6, 0.5), (120161, 125, 6, 0.4), 
    (120138, 125, 4, 0.15), (120069, 125, 4, 0.15), (120022, 125, 4, 0.15), (120002, 125, 4, 0.15), 
    (120068, 125, 2, 0.01), (120050, 125, 3, 0.05), (120139, 125, 2, 0), (120156, 125, 2, 0), 
    (120149, 126, 6, 1), (120138, 126, 4, 0.75), (120068, 126, 2, 0.50), (120127, 126, 6, 0.9), 
    (120124, 126, 6, 0.8), (120125, 126, 6, 0.7), (120130, 126, 6, 0.6), (120166, 126, 6, 0.5), 
    (120050, 126, 3, 0.45), (120161, 126, 6, 0.4), (120069, 126, 4, 0.15), (120022, 126, 4, 0.15), 
    (120002, 126, 4, 0.15), (120139, 126, 2, 0), (120156, 126, 2, 0) 
; 

давайте продолжим.


Сложная часть здесь идентифицирует три верхних вопроса в верхней категории; остальные из десяти вопросов, представляющих интерес для каждого ученика, просто сортируются по счету, что легко. Итак, давайте начнем с определения трех верхних вопросов в категории категории.

Во-первых, присвоить каждой строке номер строки, дающую порядок этот счет в этой категории, для студента:

;WITH Numbered1 (Question, Student, Category, Score, SeqInStudentCategory) AS 
(
    SELECT Question, Student, Category, Score 
     , ROW_NUMBER() OVER (PARTITION BY Student, Category ORDER BY Score DESC) SeqInStudentCategory 
    FROM WeightedScores 
) 

Теперь мы заинтересованы только в тех рядах, где SeqInStudentCategory является 1. Рассматривая только такие строки, давайте заказать их по баллам в студента, и количество этих строк:

-- within the preceding WITH 
, Numbered2 (Question, Student, Category, Score, SeqInStudent) AS 
(
    SELECT 
     Question, Student, Category, Score 
     , ROW_NUMBER() OVER (PARTITION BY Student ORDER BY Score DESC) SeqInStudent 
    FROM 
     Numbered1 
    WHERE 
     SeqInStudentCategory = 1 
) 

Теперь мы заинтересованы только в тех рядах, где SeqInStudent самое большее 3.Давайте вытаскивать их, так что мы знаем, чтобы включить его (и исключить его из простого рода по баллам, что мы будем использовать, чтобы компенсировать оставшиеся семь строк):

-- within the preceding WITH 
, TopInCat (Question, Student, Category, Score, SeqInStudent) AS 
(
    SELECT Question, Student, Category, Score, SeqInStudent FROM Numbered2 WHERE SeqInStudent <= 3 
) 

Теперь у нас есть три Топ- в категории вопросов для каждого учащегося. Теперь нам нужно определить и упорядочить по партитуре не топ-в-категории вопросов для каждого студента:

-- within the preceding WITH 
, NotTopInCat (Question, Student, Category, Score, SeqInStudent) AS 
(
    SELECT 
     Question, Student, Category, Score 
     , ROW_NUMBER() OVER (PARTITION BY Student ORDER BY Score DESC) SeqInStudent 
    FROM 
     WeightedScores WS 
    WHERE 
     NOT EXISTS (SELECT 1 FROM TopInCat T WHERE T.Question = WS.Question AND T.Student = WS.Student) 
) 

Наконец мы объединить TopInCat с NotTopInCat, применяя смещение Надлежащий и ограничение на NotTopInCat.SeqInStudent - нам нужно добавить 3 к сырому стоимости, и занять первое 7 (который 10 - 3):

-- within the preceding WITH 
, Combined (Question, Student, Category, Score, CombinedSeq) AS 
(
    SELECT 
     Question, Student, Category, Score, SeqInStudent AS CombinedSeq 
    FROM 
     TopInCat 
    UNION 
    SELECT 
     Question, Student, Category, Score, SeqInStudent + 3 AS CombinedSeq 
    FROM 
     NotTopInCat 
    WHERE 
     SeqInStudent <= 10 - 3 
) 

чтобы получить наши окончательные результаты:

SELECT * FROM Combined ORDER BY Student, CombinedSeq 
; 

Вы можете увидеть результаты on sqlfiddle.


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

Кроме того, «(как из числа вопросов, так и из категории будет переменным в конечном итоге)» должно быть относительно простым для решения здесь. Но следите за тем, что (в данном случае) 3 категории обязательно будут присутствовать в ответах каждого учащегося.

+1

Это замечательно! Благодаря! Я начал что-то вроде этого, но думал, что должен быть лучший способ. Я нашел небольшую проблему с вашим кодом. В NotTopInCat - WHERE Вопрос NOT IN не является специфическим для ученика, поэтому он должен быть ГДЕ НЕ СУЩЕСТВУЕТ (SELECT 1 FROM TopInCat TIC WHERE TIC.Student = WS.Student AND TIC.Question = WS.Question) Можете ли вы обновить ответ? Я собираюсь сделать больше проверки, но я думаю, что это, вероятно, лучшее решение. Еще раз спасибо. – cporichie

+0

@cporichie да, это было, когда я все еще думал, что «Вопрос» был ПК, а на самом деле «(Вопрос, Студент)» - это ПК. Обновление сейчас. – AakashM

Смежные вопросы