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 デモ- [Run 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 に答える