Sql server SQL语句从另一列更新三列

Sql server SQL语句从另一列更新三列,sql-server,Sql Server,我的表格结构如下: CREATE TABLE [dbo].[Ontledings]( [ont_ID] [int] IDENTITY(1,1) NOT NULL, [plaasno] [varchar](50) NOT NULL, [plaasnaam] [varchar](50) NOT NULL, [blokno] [varchar](50) NOT NULL, [plaasblok] [varchar](50) NULL, [area] [varchar](50) NOT NULL, [a

我的表格结构如下:

CREATE TABLE [dbo].[Ontledings](
[ont_ID] [int] IDENTITY(1,1) NOT NULL,
[plaasno] [varchar](50) NOT NULL,
[plaasnaam] [varchar](50) NOT NULL,
[blokno] [varchar](50) NOT NULL,
[plaasblok] [varchar](50) NULL,
[area] [varchar](50) NOT NULL,
[analisedatum] [date] NOT NULL,
[name3] [varchar](50) NULL,
[kultivar] [varchar](50) NOT NULL,
[wingklas] [varchar](50) NOT NULL,
[kultklas] [varchar](50) NULL,
[suiker] [real] NOT NULL,
[pH] [real] NOT NULL,
[suur] [real] NOT NULL,
[last] [date] NULL,
[secondlast] [date] NULL,
[thirdlast] [date] NULL,
 CONSTRAINT [PK_Ontledings] PRIMARY KEY CLUSTERED 
(
[ont_ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF,   ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
更新前,表如下所示,仅包含相关列:

然后,对于每一行,我需要根据当前年度的analisedatum列,使用该行的第三、第二和最后一个日期更新最后三列。这需要对plaasblok相同的所有行执行

结果表应如下所示: 编辑

首先,您的结构不是一个好的结构,因为在某些列中会有具有相同值的不同行,这是不好的

更好的结构是使用不同的表来处理每个plaasblok的3个最早日期。为此,您可以从Ontledings表中删除last、secondlast和thirdlast列,并使用这些列创建另一个表。然后创建一个流程,为每个plaasblok选择Ontledings表中最早的3个日期,并将它们插入新表中。这样可以避免在某些列中有具有相同值的行的大表

新表将如下所示:

plaasblok | last    | secondlast | thirdlast
03706A1   | 18/3/15 | 17/3/15    | 13/3/315
03706A2   | 17/2/15 | 16/2/15    | 10/2/315
03706A3   | 18/3/15 | 17/3/15    | 13/3/315
(...)
该过程可以执行以下选择以获得您想要的结果:

SELECT
   A.plaasblok,
   MAX(A.analisedatum) as last,
   MAX(B.analisedatum) as secondlast,
   MAX(C.analisedatum) as thirdlast
FROM Ontledings A
JOIN Ontledings B ON B.plaasblok = A.plaasblok AND B.analisedatum < A.analisedatum
JOIN Ontledings C ON C.plaasblok = B.plaasblok AND C.analisedatum < B.analisedatum
GROUP BY A.plaasblok
ORDER BY A.plaasblok ASC;

这涉及子查询中的一些自连接,以说明要查找的多个日期:

UPDATE O
SET O.last = Z.last
,   O.secondlast = Z.secondlast
,   O.thirdlast = Z.thirdlast
FROM Ontledings O
JOIN (
    SELECT X.plaasblok, MAX(X.analisedatum) AS last, MAX(P.analisedatum) AS secondlast, MAX(Q.analisedatum) AS thirdlast
    FROM Ontledings X
    JOIN Ontledings P ON P.plaasblok = X.plaasblok AND P.analisedatum < X.analisedatum
    JOIN Ontledings Q ON Q.plaasblok = P.plaasblok AND Q.analisedatum < P.analisedatum
    GROUP BY X.plaasblok
) AS Z
ON O.plaasblok = Z.plaasblok
注意:您可以使用稍微不太复杂的选择来检查值-注意每个连接的最大日期是如何级联的,以确保下一个最新日期的有效性:

SELECT O.plaasblok, MAX(O.analisedatum) AS last, MAX(P.analisedatum) AS secondlast, MAX(Q.analisedatum) AS thirdlast
FROM Ontledings O
JOIN Ontledings P ON P.plaasblok = O.plaasblok AND P.analisedatum < O.analisedatum
JOIN Ontledings Q ON Q.plaasblok = P.plaasblok AND Q.analisedatum < P.analisedatum
GROUP BY O.plaasblok
ORDER BY O.plaasblok

下面是一个使用窗口函数row_number的解决方案。首先,按降序日期对plaasblok组中的行进行编号。然后需要3个连接和更新:

;with cte as(select *, row_number() over(partition by plaasblok order by analisedatum desc) rn 
             from Ontledings)

update t set [last] = c1.analisedatum,
             [secondlast] = c2.analisedatum,
             [thirdlast] = c3.analisedatum
from Ontledings t
left join cte c1 on t.plaasblok = c1.plaasblok and c1.rn = 1
left join cte c2 on t.plaasblok = c2.plaasblok and c2.rn = 2
left join cte c3 on t.plaasblok = c3.plaasblok and c3.rn = 3

用哪些日期更新这三列?至于公共值,原始表中的公共值是什么?您需要显示数据结构或DDL。首先编写一个返回所需内容的查询。这是否返回了所需的部分内容:`SELECT Plaasblok,MINanaliseddatum GROUP BY Plaasblok。请指定SQL Server的版本,因为widowing函数似乎会派上用场。谢谢。我希望我改进后的问题更清楚。日期不是以1天为间隔。嗨,Gideon,看看你的结构,我告诉你这不是一个好的结构,因为在某些列中有不同的行具有相同的值,这不好。更好的结构是使用不同的表来处理每个plaasblok的3个最早日期。因此,您可以从Ontledings表中删除last、secondlast和thirdlast列,并将其插入另一列,然后创建一个进程以获取Ontledings表中最早的3个日期并将其插入新表,而不是更新并创建具有相同值的多行。