【问题标题】:How to decrement multiple record with same Id in different date如何在不同日期减少具有相同 ID 的多条记录
【发布时间】: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 的记录?
  • 已编辑,抱歉
  • 请格式化您的数据 - 您刚刚编辑了一些为您格式化数据的好心人。

标签: c# sql sql-server tsql


【解决方案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 替换为实体表名称。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-05-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多