2

我正在使用 SQL Server 2012,并且正在尝试执行以下操作:

SELECT SUM(MILES) from tblName WHERE 
mDate > = '03/01/2012' and 
mDate <= '03/31/2012' 
-- and...
/* 
   now I want to add here do until the SUM of Miles 
   is equal to or greater then '3250' and get the 
   results rows randomly
*/

所以换句话说,我想从一个表中选择具有指定从和到日期的随机行,并在里程总和等于或超过该数字时停止:3250

4

5 回答 5

4

由于您使用的是 SQL Server 2012,因此这是一种更简单的方法,不需要循环。

DECLARE @tbl TABLE(mDate DATE, Miles INT)

INSERT @tbl VALUES
('20120201', 520),  ('20120312', 620),
('20120313', 720),  ('20120314', 560),
('20120315', 380),  ('20120316', 990),
('20120317', 1020), ('20120412', 520);

;WITH x AS 
(
 SELECT 
   mDate, 
   Miles, 
   s = SUM(Miles) OVER 
   (
     ORDER BY NEWID() ROWS UNBOUNDED PRECEDING
   )
 FROM @tbl
 WHERE mDate >= '20120301' 
 AND mDate < '20120401'
)
SELECT 
  mDate, 
  Miles, 
  s
FROM x 
WHERE s <= 3250
ORDER BY s;

SQLfiddle 演示- 多次点击“运行 SQL”以查看随机结果。

于 2013-03-07T18:21:11.373 回答
2

你可以做得到SELECT TOP x ... ORDER BY newid()随机行的总和。问题在于确定“x”。您甚至无法确定 'x' 的最大值(与查询匹配的行数)的总和是否足以满足您的要求,而无需先进行测试:

DECLARE @stopAt int
DECLARE @x int
DECLARE @result int

SET @stopAt = 3250
SET @x = 1

SELECT @result = SUM(MILES) from tblName 
WHERE 
  mDate >= '03/01/2012' and 
  mDate <= '03/31/2012'

IF (@result < @stopAt)
  SELECT NULL -- this can't be done
ELSE
  BEGIN
    WHILE (1=1)
    BEGIN
      SELECT TOP (@x) @result = SUM(MILES) FROM tblName
      WHERE 
        mDate >= '03/01/2012' and 
        mDate <= '03/31/2012'
      ORDER BY newid()
      IF @result >= @stopAt
        BREAK
      SET @x = @x + 1
    END
    SELECT @result
  END

只是关于这一点的说明 - 算法从 1 开始并递增,直到找到合适的匹配。一种更有效的方法(对于更大的数据集)可能包括二进制类型搜索,该搜索缓存最低的合​​适结果并在找到最深的节点(或精确匹配)时返回。

于 2013-03-07T18:03:28.637 回答
0

只是一个示例代码,您可以理解这个概念。

create table temp(intt int)
insert into temp values(1)
insert into temp values(2)
insert into temp values(3)
insert into temp values(4)
insert into temp values(5)
insert into temp values(6)
insert into temp values(7)
insert into temp values(8)
insert into temp values(9)
insert into temp values(10)
insert into temp values(11)
insert into temp values(12)
insert into temp values(13)
insert into temp values(14)
insert into temp values(15)
insert into temp values(16)
insert into temp values(17)
insert into temp values(18)
insert into temp values(19)
insert into temp values(20)
insert into temp values(21)

declare @sum int = 0;
declare @prevInt int = 0;
while(@sum<50)
begin
set @prevInt = (select top(1) intt from temp order by newid());
set @sum = @sum + @prevInt;
end
set @sum = @sum-@prevInt;
select @sum
drop table temp

这种方法的原因是分页不会返回广泛分布的结果,除非并且直到您有数千条记录,因为在其中数据被分组到页面中并且记录较少,相同的页面被多次点击给出相同的结果。

此外,在某些情况下,可能会点击空白页,结果为 0。(我不知道为什么有时会点击空白页。)

于 2013-03-07T17:50:34.140 回答
0

我想不出没有 TSQL While... 循环的方法。这与使用 ROW_NUMBER() 的 TSQL 分页相结合应该可以帮助您。

http://www.mssqltips.com/sqlservertip/1175/page-through-sql-server-results-with-the-rownumber-function/

在 ROW_NUMBER 查询中,将 Miles 相加到另一个 MileSum 列中,然后在 while 循环中选择集合与 ROW_NUMBER 查询对应的所有行,同时将这些 MileSum 值累积到一个变量中。当变量超过 3250 时终止。

于 2013-03-07T18:00:55.857 回答
0

尝试

SELECT MILES
     , RANK() OVER (ORDER BY NEWID()) yourRank
FROM @tblName 
WHERE miles>3250
  AND mDate >= '03/01/2012' 
  AND mDate <= '03/31/2012'
ORDER BY yourRank

然后你可以添加一个 TOP 5 或任何你想要的。您肯定会以随机顺序获得它们。

于 2013-03-07T18:02:23.607 回答