SQL - 返回数据子集的项目排名

时间:2014-06-16 15:14:06

标签: mysql sql

我想获得一些关于在表格中对数据子集进行编号并返回完整数据集的最佳方法的指导。

我的数据集大约有50万条记录。数据库保存测试结果,每行都是问题的答案。一个人进行了2次测试,但这些测试可能是20次左右的测试中的2次。

数据如下所示:

PersonID    TestID    QuestionID
UID-1       T-1       QuA-1
UID-1       T-1       QuA-2
UID-1       T-1       QaA-3
UID-1       T-2       QuB-1
UID-1       T-2       QuB-2
UID-1       T-2       QuB-3
UID-2       T-1       QuA-1
UID-2       T-3       QuC-1

我的目标是返回带有数字的数据集,以表示测试是第一个还是第二个测试(顺序不重要,我只需要为他们的TestID分配1或2)。同样,我也需要对问题进行编号。

说一个人做2次测试,第一次有15个问题,第二次有20个问题,这是我想要的输出:

PersonID    TestID    QuestionID   TestNum   QuNum
UID-1       T-1       QuA-1        1         1
UID-1       T-1       ...          1         ...
UID-1       T-1       QaA-15       1         15
UID-1       T-2       QuB-1        2         1
UID-1       T-2       ...          2         ...
UID-1       T-2       QuB-20       2         20

对于每个人,测试编号将为1或2,测试的问题数量将从1开始,并逐渐增加到最后一个问题。

你会用什么方法?

1 个答案:

答案 0 :(得分:0)

据我所知,在SQL中执行此操作的唯一方法是使用" CURSORS"。

在声明游标之前,我从原始表创建一个新表,并将两个新列(即testNum和questionNum)添加到默认值或0中。这是使用"选择"。

完成的

然后,通过游标逐个读取该表的记录(并命令),我检查personId和testId是否发生变化,并根据它们的状态决定(更新当前问题和测试的两个计数器)。

在循环结束时,在读取下一条记录之前,使用两个计数器更新表格(对于当前问题和当前测试)。

这里有代码(顺便说一下,我还没有测试过。所以请注意拼写错误或可能是小错误):

SELECT personId, testId, 0 as testNum, 0 as questionNum into t1
    FROM Questions

DECLARE c1 CURSOR FOR 
    SELECT *
        FROM t1
        ORDER BY personId, testId, questionId
OPEN c1
declare @lastPersonId varchar(10);
declare @lastTestId varchar(10);
declare @currentTestNum int;
declare @currentQuestionNum int;

set @lastPersonId = "-1";
set @lastTestId = "-1";
set @currentTestNum = 1;
set @currentQuestionNum = 1;

FETCH NEXT FROM c1
    INTO @personId, @testId, @questionId, @testNum, @qNum

WHILE @@FETCH_STATUS = 0
    BEGIN
    if (@personId <> @lastPersonId) 
        begin
        @currentTestNum = 1
        @currentQuestionNum = 1     
        end
    else
        if (@testId <> @lastTestId)         
            begin
            @currentTestNum = @currentTestNum + 1
            @currentQuestionNum = 1     
            end
        else -- in this case it is assumed that the questions are different.
            set @currentQuestionNum = @currentQuestionNum + 1

    update t1
        set testNum = @currentTestNum, questionNum = @currentQuestionNum
        where current of c1

    set @lastPersonId = @personId
    set @lastTestId = @testId
    FETCH NEXT FROM c1
        INTO @personId, @testId, @testNum, @qNum
    END  

CLOSE c1;
DEALLOCATE c1;