我有一个Ledger
表:
CREATE TABLE Ledger
(
PersonID int,
Narration varchar(255),
Payment int(255)
);
INSERT INTO Ledger(PersonID, Narration, Payment)
VALUES (1, 'Snacks 1', 5);
INSERT INTO Ledger(PersonID, Narration, Payment)
VALUES (1, 'Snacks 2', 10);
INSERT INTO Ledger(PersonID, Narration, Payment)
VALUES (2, 'Snacks 3', 7);
INSERT INTO Ledger(PersonID, Narration, Payment)
VALUES (1, 'Snacks 4', 6);
INSERT INTO Ledger(PersonID, Narration, Payment)
VALUES (2, 'Snacks 5', 3);
INSERT INTO Ledger(PersonID, Narration, Payment)
VALUES (1, 'Snacks 6', 1);
表格如下:
PersonID Narration Payment
_____________________________________________
1 Snacks 1 5
1 Snacks 2 10
2 Snacks 3 7
1 Snacks 4 6
2 Snacks 5 3
1 Snacks 6 1
此处PersonID=1
完全花了22,PersonID=2
完全花了10。
我的要求是将总Payment
减少到低于或等于20. 没有唯一列。 我希望删除记录,使总Payment
低于或等于20 。
在上表中,PersonID=1
的总Payment
大于20,因此我需要删除一些记录以减少总付款。
我的预期输出
PersonID Narration Payment
_____________________________________________
1 Snacks 2 10
2 Snacks 3 7
1 Snacks 4 6
2 Snacks 5 3
1 Snacks 6 1
我在这里删除了
1 Snacks 1 5
现在Payment
的总PersonID=1
为17,低于20。
基于逻辑,我们必须删除记录。
请在SQL Server和MySQL中帮助我。我的第一个偏好是SQL Server。
答案 0 :(得分:3)
以下是SQL Server 2012 +的一种可能变体。
示例数据
CREATE TABLE Ledger
(
PersonID int,
Narration varchar(255),
Payment int
);
INSERT INTO Ledger(PersonID, Narration, Payment) VALUES
(1, 'Snacks 1', 5),
(1, 'Snacks 2', 10),
(2, 'Snacks 3', 7),
(1, 'Snacks 4', 6),
(2, 'Snacks 5', 3),
(1, 'Snacks 6', 1);
SELECT *
FROM Ledger
ORDER BY PersonID, Payment;
+----------+-----------+---------+
| PersonID | Narration | Payment |
+----------+-----------+---------+
| 1 | Snacks 6 | 1 |
| 1 | Snacks 1 | 5 |
| 1 | Snacks 4 | 6 |
| 1 | Snacks 2 | 10 |
| 2 | Snacks 5 | 3 |
| 2 | Snacks 3 | 7 |
+----------+-----------+---------+
<强>查询强>
我们可以计算运行总计来确定我们要保留哪些行以及要删除哪些行。您可以通过选择运行总计中的排序来调整行选择的逻辑。在此示例中,我将从最小的Payment
开始计算运行总计,因此将保留最小Payment
的行。
此查询显示计算,以了解其工作原理:
WITH
CTE
AS
(
SELECT
PersonID
,Narration
,Payment
,SUM(Payment) OVER
(PARTITION BY PersonID ORDER BY Payment
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS ss
FROM Ledger
)
SELECT *
FROM CTE
ORDER BY PersonID, Payment;
+----------+-----------+---------+----+
| PersonID | Narration | Payment | ss |
+----------+-----------+---------+----+
| 1 | Snacks 6 | 1 | 1 |
| 1 | Snacks 1 | 5 | 6 |
| 1 | Snacks 4 | 6 | 12 |
| 1 | Snacks 2 | 10 | 22 |
| 2 | Snacks 5 | 3 | 3 |
| 2 | Snacks 3 | 7 | 10 |
+----------+-----------+---------+----+
此查询实际上删除了行:
WITH
CTE
AS
(
SELECT
PersonID
,Narration
,Payment
,SUM(Payment) OVER
(PARTITION BY PersonID ORDER BY Payment
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS ss
FROM Ledger
)
DELETE FROM CTE
WHERE ss > 20;
<强>结果强>
SELECT *
FROM Ledger
ORDER BY PersonID, Payment;
+----------+-----------+---------+
| PersonID | Narration | Payment |
+----------+-----------+---------+
| 1 | Snacks 6 | 1 |
| 1 | Snacks 1 | 5 |
| 1 | Snacks 4 | 6 |
| 2 | Snacks 5 | 3 |
| 2 | Snacks 3 | 7 |
+----------+-----------+---------+
答案 1 :(得分:0)
您还可以通过以下查询获取所需的输出: -
DECLARE @PID int ,@PID1 int,@Narr VARCHAR(250),@Payment decimal(18,2),@Payment1 decimal(18,2),@cnt int
SET @cnt = 20
set @Payment1=0
set @PID1=0
Create table #t1(PersonID int,Narration varchar(250),Payment decimal(18,2));
DECLARE db_cursor CURSOR FOR
SELECT PersonID,Narration,Payment from Ledger order by personid ,Payment
OPEN db_cursor
FETCH NEXT FROM db_cursor INTO @PID,@Narr,@Payment
WHILE @@FETCH_STATUS = 0
BEGIN
if (@PID1 <> @PID)
BEGIN
SET @Payment1 = 0
END
set @PID1 = @PID
SET @Payment1 = @Payment1 + @Payment
If(@Payment1 <= 20)
begin
Insert into #t1(PersonID,Narration,Payment)
values(@PID,@Narr,@Payment)
end
FETCH NEXT FROM db_cursor INTO @PID,@Narr,@Payment
end
CLOSE db_cursor
DEALLOCATE db_cursor
select * from #t1
order by personid
drop table #t1
测试相同并得到以下输出以下输入: -
输入: -
1 Snacks 1 5
1 Snacks 2 10
1 Snacks 4 6
1 Snacks 6 1
2 Snacks 5 3
2 Snacks 3 7
3 Snacks 7 15
3 Snacks 8 15
4 Snacks 9 10
输出: -
1 Snacks 6 1.00
1 Snacks 1 5.00
1 Snacks 4 6.00
2 Snacks 5 3.00
2 Snacks 3 7.00
3 Snacks 7 15.00
4 Snacks 9 10.00