22,207
社区成员
发帖
与我相关
我的任务
分享
DECLARE @tbl TABLE (
id INT IDENTITY(1,1) NOT NULL,
name VARCHAR(20),
score DECIMAL(18,2)
)
INSERT INTO @tbl(name, score)
SELECT 'a', 80 UNION SELECT 'b', 90 UNION SELECT 'c', 70 UNION SELECT 'd', 60
DECLARE @Name VARCHAR(20),
@Score DECIMAL(18,2),
@TotScore DECIMAL(18,2),
@TmpScore DECIMAL(18,2),
@TmpName VARCHAR(2000)
SELECT * FROM @tbl ORDER BY id DESC
/*
id name score
----------- -------------------- ---------------------------------------
4 d 60.00
3 c 70.00
2 b 90.00
1 a 80.00
*/
--传入数字参数
SET @TotScore=100
SET @TmpScore=0
SET @TmpName=''
DECLARE tbl CURSOR FOR
SELECT name, score FROM @tbl ORDER BY id DESC
OPEN tbl
FETCH NEXT FROM tbl INTO @Name, @Score
WHILE @@FETCH_STATUS=0
BEGIN
SET @TmpScore=@TmpScore+@Score
SET @TmpName=@TmpName+','+@Name
IF @TmpScore<@TotScore
BEGIN
FETCH NEXT FROM tbl INTO @Name, @Score
END
ELSE
BREAK;
END
CLOSE tbl
DEALLOCATE tbl
SELECT @TmpName, @TmpScore
/*
RetNames RetScore
-------------------------------- ---------------------------
,d,c 130
*/
DECLARE @tbl TABLE (
id INT IDENTITY(1,1) NOT NULL,
name VARCHAR(20),
score DECIMAL(18,2)
)
INSERT INTO @tbl(name, score)
SELECT 'a', 80 UNION SELECT 'b', 90 UNION SELECT 'c', 70 UNION SELECT 'd', 60
DECLARE @TotScore INT= 100
SELECT
(SELECT ','+Name
FROM @tbl AS a
WHERE NOT EXISTS( SELECT 1
FROM @tbl
WHERE id > a.id
HAVING SUM(score) >= @TotScore
)
ORDER BY ID DESC
FOR XML PATH('')) AS RetNames
,@TotScore AS RetScore
/*
RetNames RetScore
,d,c 100
*/
DECLARE @tbl TABLE (
id INT IDENTITY(1,1) NOT NULL,
name VARCHAR(20),
score DECIMAL(18,2)
)
INSERT INTO @tbl(name, score)
SELECT 'a', 80 UNION SELECT 'b', 90 UNION SELECT 'c', 70 UNION SELECT 'd', 60
DECLARE @TotScore INT= 150
SELECT
(SELECT ','+Name
FROM @tbl AS a
WHERE NOT EXISTS( SELECT 1
FROM @tbl
WHERE id > a.id
HAVING SUM(score) >= @TotScore
)
FOR XML PATH('')) AS RetNames
,@TotScore AS RetScore
/*
RetNames RetScore
,b,c,d 150
*/
--传入数字参数
SET @TotScore=100
;WITH a AS ( -- 生成序号
SELECT *,
ROW_NUMBER() OVER(ORDER BY id DESC) rn
FROM @tbl
)
,b AS ( -- 递归
SELECT rn,
CONVERT(VARCHAR(2000),','+name) TmpName,
CONVERT(DECIMAL(18,2),Score) TmpScore
FROM a
WHERE rn = 1
UNION ALL
SELECT a.rn,
CONVERT(VARCHAR(2000),b.TmpName+','+a.name) TmpName,
CONVERT(DECIMAL(18,2),b.TmpScore+a.Score) TmpScore
FROM b
JOIN a
ON a.rn = b.rn + 1
WHERE b.TmpScore < @TotScore -- 找到后直接终止递归
)
SELECT TOP 1
@TotScore TotScore,
TmpName,
TmpScore
FROM b
ORDER BY rn DESC
TotScore TmpName TmpScore
---------- ---------- ----------
100.00 ,d,c 130.00
;WITH a AS ( -- 生成序号
SELECT *,
ROW_NUMBER() OVER(ORDER BY id DESC) rn
FROM @tbl
)
,b AS ( -- 递归
SELECT rn,
CONVERT(VARCHAR(2000),','+name) TmpName,
CONVERT(DECIMAL(18,2),Score) TmpScore
FROM a
WHERE rn = 1
UNION ALL
SELECT a.rn,
CONVERT(VARCHAR(2000),b.TmpName+','+a.name) TmpName,
CONVERT(DECIMAL(18,2),b.TmpScore+a.Score) TmpScore
FROM b
JOIN a
ON a.rn = b.rn + 1
/* 或者可以先取得最大的参数用来过滤,进行优化
WHERE b.TmpScore < @MaxTotScore
*/
)
,c(TotScore) AS ( -- 模拟多个要查的参数
SELECT CONVERT(DECIMAL(18,2),60) UNION ALL
SELECT 70 UNION ALL
SELECT 100 UNION ALL
SELECT 130 UNION ALL
SELECT 150 UNION ALL
SELECT 290 UNION ALL
SELECT 310
)
SELECT c.TotScore,
CONVERT(varchar(10),t.TmpName) TmpName,
t.TmpScore
FROM c
OUTER APPLY (
SELECT TOP 1 *
FROM b
WHERE b.TmpScore >= c.TotScore
ORDER BY b.rn
) t
OPTION (MAXRECURSION 0) -- 10000多条数据全部递归
TotScore TmpName TmpScore
---------- ---------- ----------
60.00 ,d 60.00
70.00 ,d,c 130.00
100.00 ,d,c 130.00
130.00 ,d,c 130.00
150.00 ,d,c,b 220.00
290.00 ,d,c,b,a 300.00
310.00 NULL NULL