如何在不同日期减少具有相同 ID 的多条记录
Posted
技术标签:
【中文标题】如何在不同日期减少具有相同 ID 的多条记录【英文标题】:How to decrement multiple record with same Id in different date 【发布时间】:2019-12-12 20:57:06 【问题描述】:我在一张表中有一些记录,它们的 ID 相同,但日期和数量不同。
Id | Date | Name | Volume
1 | 01/08/2019 | Item | 2
1 | 02/08/2019 | Item | 3
1 | 03/08/2019 | Item | 5
然后我有一个销售表格,每次用户销售物品时都会减少数量。
我希望它是这样的: 当用户一次卖出 7 件时,减量是这样的
Id | Date | Name | Volume
1 | 01/08/2019 | Item | 0
1 | 02/08/2019 | Item | 0
1 | 03/08/2019 | Item | 3
从最早的日期开始,当日期的音量不够时,它会减少下一个最旧的日期
但我不知道如何循环。
【问题讨论】:
您的示例数据没有任何具有相同 id 的记录? 已编辑,抱歉 请格式化您的数据 - 您刚刚编辑了一些为您格式化数据的好心人。 【参考方案1】:这里是怎么做的
CREATE TABLE T(
Id INT,
Date DATE,
Name VARCHAR(45),
Volume INT
);
INSERT INTO T VALUES
(1, '2019-08-01', 'Item', 2),
(1, '2019-08-02', 'Item', 3),
(1, '2019-08-03', 'Item', 5);
SELECT *, CASE WHEN SUM(Volume) OVER(PARTITION BY Id ORDER BY Date) < V THEN 0
ELSE SUM(Volume) OVER(PARTITION BY Id ORDER BY Date) - V
END Result
FROM T CROSS JOIN (VALUES(7)) TT(V);
如果你要去UPDATE
桌子:
WITH CTE AS
(
SELECT *, CASE WHEN SUM(Volume) OVER(PARTITION BY Id ORDER BY Date) < V THEN 0
ELSE SUM(Volume) OVER(PARTITION BY Id ORDER BY Date) - V
END Result
FROM T CROSS JOIN (VALUES(7)) TT(V)
)
UPDATE T
SET Volume = CTE.Result
FROM T JOIN CTE
ON T.Id = CTE.Id
AND
T.Date = CTE.Date;
Demo
更新:
这是一个使用相关子查询的新查询
WITH A AS
(
SELECT *,
(
SELECT SUM(TT.Volume)
FROM T TT
WHERE TT.Id = T.Id
AND
TT.Date <= T.Date
AND
T.Volume >= TT.Volume
) R
FROM T
)
SELECT T.*, CASE WHEN R < 7 THEN 0 ELSE R - 7 END Result
FROM T JOIN A
ON T.Id = A.Id AND T.[Date] = A.[Date];
Demo for the Correlated subquery
【讨论】:
什么是 TT(V)? @Keanu1701 这是一个包含已售商品数量的表格,您可以将其删除并直接使用7
而不是V
列,就像this跨度>
Msg 102, Level 15, State 1, Line 3 'order' 附近的语法不正确。消息 102,级别 15,状态 1,第 5 行“结果”附近的语法不正确。
你查看我刚刚给你@Keanu1701 的链接了吗?因为它对我来说很好,除非你有一些你没有告诉它的东西。将列包装在[]
是的,在浏览器代码编辑器中可以正常工作,我使用的是 SQL Server 2008【参考方案2】:
试试下面的代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
namespace ConsoleApplication124
class Program
static void Main(string[] args)
DataTable dt = new DataTable();
dt.Columns.Add("Id", typeof(int));
dt.Columns.Add("Date", typeof(DateTime));
dt.Columns.Add("Name", typeof(string));
dt.Columns.Add("Volume", typeof(int));
dt.Rows.Add(new object[] 1, DateTime.Parse("08/01/2019"), "Item", 2);
dt.Rows.Add(new object[] 1, DateTime.Parse("08/02/2019"), "Item", 3 );
dt.Rows.Add(new object[] 1, DateTime.Parse("08/03/2019"), "Item", 5 );
dt = dt.AsEnumerable().OrderBy(x => x.Field<DateTime>("Date")).CopyToDataTable();
int order = 7;
foreach(DataRow row in dt.AsEnumerable().Where(x => x.Field<int>("Id") == 1))
int oldVolume = row.Field<int>("Volume");
if (oldVolume >= order)
row["Volume"] = row.Field<int>("Volume") - order;
break;
else
order -= oldVolume;
row["Volume"] = 0;
【讨论】:
是否使用EF? 我只是把数据放到一个DataTable中。实体也使用 DataTable。您只需将我的代码中的 dt 替换为实体表名称。以上是关于如何在不同日期减少具有相同 ID 的多条记录的主要内容,如果未能解决你的问题,请参考以下文章
Laravel,如何在 HTML 表格中输出相同 ID 的多条记录?
SQL 如何将一个表中的两条或多条拥有相同ID的记录合并为一条?