如何选择列总和满足Sql server中条件的随机行

时间:2017-11-07 09:24:14

标签: sql-server

是否可以从特定列总和(总和)应小于条件值的表中选择随机行?

我的表结构就像 -

id | question | answerInSec
1  | Quest1   | 15
2  | Quest2   | 20
3  | Quest3   | 10
4  | Quest4   | 15
5  | Quest5   | 10
6  | Quest6   | 15
7  | Quest7   | 20

我想得到那些'answerInSec'列总和小于(最接近总数)或等于60的随机问题。

所以随机组合可以是[1,2,3,4] OR [2,3,5,7] OR [4,5,6,7]等。

我尝试如下但没有运气

select id,question,answerinsec
from (select Question.*, sum(answerinsec) over (order by id) as CumTicketCount
      from Question 
     ) t 
where cumTicketCount <= 60
ORDER BY NEWID();

3 个答案:

答案 0 :(得分:1)

我希望这个帮助

DECLARE @MaxAnswerInSec INT = 60
DECLARE @SumAnswerInSec INT = 0
DECLARE @RadomQuestionTable TABLE(Id INT, Question NVARCHAR(100), AnswerInSec INT)

DECLARE @tempId INT, 
        @tempQuestion NVARCHAR(100), 
        @tempAnswerInSec INT

WHILE @SumAnswerInSec <= @MaxAnswerInSec
BEGIN       
    SELECT TOP(1) @tempId = Id, @tempQuestion = Question, @tempAnswerInSec = AnswerInSec
    FROM Question 
    WHERE Id NOT IN (SELECT Id FROM @RadomQuestionTable) 
    AND AnswerInSec + @SumAnswerInSec <= @MaxAnswerInSec
    ORDER BY NEWID()    

    IF @tempId IS NOT NULL
    BEGIN
        INSERT INTO @RadomQuestionTable VALUES(@tempId, @tempQuestion, @tempAnswerInSec)
    END
    ELSE
    BEGIN   
        BREAK
    END

    SELECT @tempId = NULL
    SELECT @SumAnswerInSec = SUM(AnswerInSec) FROM @RadomQuestionTable  
END

SELECT * FROM @RadomQuestionTable

答案 1 :(得分:0)

行。试试这个。这可能不是最快的,但更容易理解和实施。此外,这是一个仅限SQL的解决方案:

<form novalidate name="newTripForm" ng-submit="vm.addTrip()">
  <div class="form-group" ng-init="vm.newTrip.name = '';">
      <label for="name">Trip Name</label>
      <input type="text" class="form-control" id="name" name="name"  ng-model="vm.newTrip.name" required/>
  </div>
  <div class="form-group">
       <input type="submit"  class="btn btn-sm btn-success" id="submit" value="Add"/>
  </div>  

这基本上做的是创建问题表与自身的交叉产品,然后再重复此过程两次,从而创建SELECT t1.id, t2.id, t3.id, t4.id FROM Question t1 CROSS JOIN Question t2 CROSS JOIN Question t3 CROSS JOIN Question t4 WHERE t2.id > t1.id AND t3.id > t2.id AND t4.id > t3.id AND t1.answerInSec + t2.answerInSec + t3.answerInSec + t4.answerInSec = 60 行,其中N是表中的行数。然后,它只会选择那些选择N ^ 4的排列的行来过滤掉重复的行。然后通过查找所有得分字段总和等于目标值的行来过滤剩余的行(60)。

请注意,即使是中等大小的表,此结果集也会变得很大。例如,一个只有200行的表将生成200 ^ 4 = 1,600,000,000行的叉积(尽管其中很多行将被t1.id < t2.id < t3.id < t4.id子句丢弃)。如果您的表很大,您应该准备好索引。

另请注意,此查询不考虑少于4行可以合计为60的排列。您可以通过在表中包含NULL行(得分字段为零的行)轻松修改它来执行此操作。

答案 2 :(得分:0)

SELECT      *
FROM        question
WHERE       answerInSec<50
ORDER BY    CHECKSUM(NEWID())