如何在不同日期减少具有相同 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 的多条记录?

如何在 C# 中迭代​​数组值并更新多条记录 [关闭]

SQL 如何将一个表中的两条或多条拥有相同ID的记录合并为一条?

如何在不同时间获得相同ID的每个部分的最小日期? - SQL 服务器

如何获取具有相同app_id列但不同手机号码列的下一条记录

如何在 Rails 中选择通过连接到另一个具有多条记录的表的最新记录