【问题标题】:SQL set column equal to another column from previous month for each unique value of separate column对于单独列的每个唯一值,SQL 设置列等于上个月的另一列
【发布时间】:2016-09-04 08:02:23
【问题描述】:

对于这个问题看起来多么复杂,我提前道歉,但这就是我要处理的问题。我有一张表,里面有 500 万多条记录。在这 500 万多条记录中,我有大约 185,000 个唯一值,我称之为 Column1。 Column1 是一个 varchar 字段。然后我有一个日期字段,我将其称为 Column2,它是一个日期字段,范围从“2005-01-01”到当前日期。对于每条记录,都有一个浮点字段,我将其称为 Column3。 Column3 保存该特定记录的当前汇率。然后有一个不同的浮点字段,我将其称为 Column4。该字段包含我需要设置的最后一个速率字段,该字段等于我从 Column2 获得的上个月 Column3 的值。棘手的部分是我需要为 Column1 的每个唯一值执行此操作。我希望这是有道理的。现在我在 Column4 中的所有数据都是空的,但我希望它看起来像你在下面看到的那样。

例如:

Column1      Column2      Column3      Column4
Record1      2005-01-01   6.25         6.25
Record2      2005-01-01   5.625        5.625
Record3      2005-01-01   4.75         4.75

Record1      2005-02-01   6.5          6.25
Record2      2005-02-01   5.625        5.625
Record3      2005-02-01   4.75         4.75

Record1      2005-03-01   6.75         6.5
Record2      2005-03-01   5.625        5.625
Record3      2005-03-01   5            4.75

如您所见,在某些情况下,每个月的费率都保持不变,就像 Record2 一样。但是,有时它会像 Record1 一样经常更改。还有其他时候它只改变一次,就像 Record3 一样。请让我知道您的建议,并提前感谢您。

【问题讨论】:

  • 这可能比你想象的要容易。如果您可以提供一些详细信息,我们可以提供帮助。这是一个很好的起点。 spaghettidba.com/2015/04/24/…
  • Column4 中的前 3 个值应该为 NULL,因为它们没有以前的记录。如果您使用窗口函数,例如,您的任务非常简单。 ROW_NUMBER().
  • @John Cowles_关于column2的一个问题:总是yyyy-MM-01吗?如果不是,当column22005-03-312005-03-302005-01-02 时,column4 应该是什么?
  • @peter.petrov 你是对的。为了提供示例,我使用了这些日期,但完成后 '2005-01-01' 中的所有值最终都将为 NULL。
  • @PhamX.Bach 该日期将始终在每月的第一天。我运行另一个更新语句,将值硬编码为当月的第一天。所以数据库中永远不会有 -2005-03-30 或 2005-01-02 的实例。

标签: sql sql-server sql-server-2008 tsql sql-update


【解决方案1】:

您可以使用自左连接来获取之前的值,如下所示:

declare @t table (column1 varchar(10), column2 datetime, column3 float, column4 float)

insert into @t (column1, column2, column3)
select 'RecordA', '2005-01-01', 6.25 union all
select 'RecordB', '2005-01-01', 5.625 union all
select 'RecordC', '2005-01-01', 4.75 union all
select 'RecordA', '2005-02-01', 6.5 union all
select 'RecordB', '2005-02-01', 5.625 union all
select 'RecordC', '2005-02-01', 4.75 union all
select 'RecordA', '2005-03-01', 6.75 union all
select 'RecordB', '2005-03-01', 5.625 union all
select 'RecordC', '2005-03-01', 5

update cur
set column4 = pre.column3 
from @t as cur
left join @t as pre on
    cur.column1 = pre.column1 and
    dateadd(mm, -1, cur.column2) = pre.column2 


select * 
from @t 
order by column2, column1

【讨论】:

  • 请耐心等待,因为这是我第一次在 Stack Overflow 上发帖……我复制并粘贴了您的代码,它完全按照我的意愿工作。然而,我遇到的问题是有 185,000 条唯一记录。所以它不仅仅是 RecordA、RecordB、RecordC……还有 RecordD、RecordE、RecordF 等。也许如果我给它一个不同的命名约定会更有意义。将这些记录视为 Record1、Record2 和 Record3。最后一条记录是 Record185000。我无法为每条记录硬核所有这些值。这些附加信息有帮助吗?
  • @JohnCowles - 我只是发布了一个带有示例数据的示例。您需要做的就是使用以update 开头的代码并将@t 替换为您的实际表名
  • 抱歉给您带来了困惑。我按照你说的做了,我相信它有效。我仍然会做一些验证,但我认为你已经解决了我的头痛问题。非常感谢!
猜你喜欢
  • 2018-08-05
  • 2018-04-02
  • 1970-01-01
  • 2011-12-10
  • 1970-01-01
  • 2016-05-06
  • 2016-03-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多