4

我不能爲我的生活弄清楚如何獲得X類別分數的加權排名。例如,學生需要回答3個類別中的10個問題(問題#和類別#最終都會變化)。爲了獲得總分,每個X(3)類別中的前1分將被添加到剩下的總共10個問題分數中。這是否需要遞歸CTE,只是創意窗口函數,循環?

這是數據。我用了一個CASE WHEN 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 | 

這是我的設想,它需要看,但它不一定是這個。我只需要按3種類別的詳細數據提供10個問題,這樣可以使我對下面的排序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)閾值,類別不再重要。所以第四類可以正常排序。

 
| 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 
) 

現在我們只是在行,其中SeqInStudentCategory1感興趣。僅考慮這樣的行,讓我們的學生中得分,並且數量責令這些行:

-- 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) 
) 

最後,我們用NotTopInCat結合TopInCat,施加適當的偏移和限制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不是特定於學生,所以它應該是WHERE NOT EXISTS(SELECT 1 FROM TopInCat TIC WHERE TIC.Student = WS.Student和TIC.Question = WS.Question)你能更新答案嗎?我會做更多的驗證,但我認爲這可能是最好的解決方案。再次感謝。 – cporichie

+0

@cporichie啊是的,那時候我還在想'問題'是PK,其實'(Question,Student)'是PK。現在更新。 – AakashM