Mysql SQL-返回数据子集的项排序

Mysql SQL-返回数据子集的项排序,mysql,sql,Mysql,Sql,我想要一些关于在我的表中对数据子集进行编号并返回完整数据集的最佳方法的指导 我的数据集大约有5万条记录。数据库保存测试结果,每一行都是一个问题的答案。一个人做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

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

我的数据集大约有5万条记录。数据库保存测试结果,每一行都是一个问题的答案。一个人做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
我的目标是返回带有数字的数据集,以指示测试是第一个测试还是第二个测试(顺序并不重要,我只需要为他们的测试分配1或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开始,并逐渐增加到最后一个问题


您将使用什么方法?

据我所知,在SQL中执行此操作的唯一方法是使用“游标”

在声明游标之前,我从原始表创建一个新表,并向其中添加两个新列(即testNum和questionNum),其中包含默认值或0。这是通过“选择进入”完成的

然后,通过游标逐个(并按顺序)读取该表的记录,我检查personId和testId是否更改,并根据它们的状态做出决定(更新当前问题N和测试的两个计数器)

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

下面是代码(顺便说一句,我还没有测试它。所以要注意打字错误或可能的小错误):

在t1中选择personId、testId、0作为testNum、0作为questionNum
从问题
为声明c1游标
挑选*
从t1开始
按personId、testId、questionId排序
开放式c1
声明@lastPersonId varchar(10);
声明@lastestid varchar(10);
声明@currentTestNum int;
声明@currentQuestionNum int;
设置@lastPersonId=“-1”;
设置@lastTestId=“-1”;
设置@currentTestNum=1;
设置@currentQuestionNum=1;
从c1取下一个
进入@personId、@testId、@questionId、@testNum、@qNum
而@@FETCH\u STATUS=0
开始
if(@personId@lastPersonId)
开始
@currentTestNum=1
@currentQuestionNum=1
结束
其他的
if(@testId@lastTestId)
开始
@currentTestNum=@currentTestNum+1
@currentQuestionNum=1
结束
否则——在这种情况下,假设问题是不同的。
设置@currentQuestionNum=@currentQuestionNum+1
更新t1
设置testNum=@currentTestNum,questionNum=@currentQuestionNum
其中c1的电流
设置@lastPersonId=@personId
设置@lastTestId=@testId
从c1取下一个
进入@personId、@testId、@testNum、@qNum
结束
关闭c1;
解除分配c1;

这听起来有点像XY问题。一旦你得到了数据,你想用它做什么?这是不是在表示层比在数据库引擎中更容易处理?或者,您是在尝试基于此查询聚合数据吗?我希望这些输出能够帮助解决演示问题。我可以在Excel中执行此操作,但单元格引用太大,会显著降低文件速度。我希望有一种方法可以在MySQL中实现,这样我就可以在服务器上而不是本地计算机上施加压力。在演示层中,每个人有一行,列中列出他们的问题回答和总体分数。我还使用这一每人一行的数据集对测试统计数据进行分析。您是直接将其导出到excel,还是中间有一些代码?如果您对{PersonID asc,TestID asc,QuestionID asc}上的结果进行排序,您可以简单地增加计数器,并在从结果中获取行时对照前一行检查每一行的值。由于您无论如何都必须获取行,因此当数据进入时,存储和比较值的开销应该很小。我直接导出到Excel。您概述的方法实际上就是我目前在Excel中所做的。你能在柜台上再扩大一点吗?我不擅长SQL。我需要将它与CASE结合使用吗?对不起,我指的是计数器,我说的是正常的过程代码。您可以使用VBA轻松地执行此操作,而不必尝试使用公式。只需在行中循环一次,并跟踪上一个值。TestID更改时,增加TestNum并重置QuNum。当PersonID更改时,重置TestNum和QuNum。
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;