0

我有一个包含字段(QuestionID,QuestionMarks)的问题表,并且数据字段看起来像 -

 QuestionID   QuestionMarks
   1              1
   2              4
   5              1
   9              1
   12             2

这意味着目前问题表有 5 个问题,共 9 个分数,现在我的问题是我想知道 4 个问题与 8 个分数的组合是可能的并取出该组合(通常是“x”问题的组合“y”标记是可能的)?

我正在考虑使用 CTE,但担心如果我有数万个问题会花费大量时间来执行查询。

请提出一些想法如何获取数据。我正在使用 SQL Server 2008 版

4

2 回答 2

0

这是一个开始。它的性能会很差:

declare @Qs table (QuestionID int not null, QuestionMarks int not null)
insert into @Qs (QuestionID,QuestionMarks) values
(1,1), (2,4), (5,1), (9,1), (12,2)

declare @TargetMarks int = 8
declare @TargetCount int = 4

;with Build as (
    select QuestionID as MinID,QuestionID as MaxID,QuestionMarks as Total,1 as Cnt
        ,'/' + CONVERT(varchar(max),QuestionID) + '/' as QPath
    from @Qs
    union all
    select MinID,q.QuestionID,Total+q.QuestionMarks,Cnt+1,QPath + CONVERT(varchar(max),q.QuestionID) + '/'
    from
        Build b
            inner join
        @Qs q
            on
                b.MaxID < q.QuestionID and
                b.Total + q.QuestionMarks <= @TargetMarks and
                b.Cnt < @TargetCount
)
select * from Build where Cnt = @TargetCount and Total = @TargetMarks

结果集:

MinID       MaxID      Total       Cnt         QPath
--------------------------------------------------------------------------------
2           12          8           4           /2/5/9/12/
1           12          8           4           /1/2/9/12/
1           12          8           4           /1/2/5/12/

棘手的部分是 QPath 值并不是存储 ID 值的最佳方式。

于 2012-07-08T05:27:45.463 回答
0

我认为你是对的,数以万计的问题会减慢执行速度,所以我首先限制被查询的潜在行。您已经确定即使有数百万行,您也永远不需要超过四个具有相同问号的行,您可以进一步减少这一点,例如(抱歉不知道 SQL Server 是否接受此语法)

WITH LimitPotentialRows AS 
(SELECT m1.QuestionID, m1.QuestionMarks, 
 (SELECT SUM(m2.QuestionMarks)
  FROM MyTable m2
  WHERE m1.QuestionMarks = m2.QuestionMarks
    AND m1.PrimaryKeyID <= m2.PrimaryKeyID) CurrentMarks,
 (SELECT COUNT(*)
  FROM MyTable m3
  WHERE m1.QuestionMarks = m3.QuestionMarks
    AND m1.PrimaryKeyID <= m3.PrimaryKeyID) TotalQuestions
 FROM MyTable m1
 WHERE m1.QuestionMarks <= :DesiredTotalQuestionMarks - :TotalNoOfQuestions + 1
 HAVING CurrentMarks <= :DesiredTotalQuestionMarks
    AND TotalQuestions <= :TotalNoOfQuestions)

求4题,总分8分,本次CTE成绩只剩下

QuestionMarks NumberOfQuestions
       1              4
       2              4
       3              2
       4              1
       5              1

将行数从数万限制到最多 12 行,您在进一步计算中不太可能遇到性能问题。

于 2012-07-08T07:40:47.063 回答