2015-12-14 108 views
0

我的表的结构如下:SQL语句从另一列更新三列

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] 

更新前表如下所示(仅适用于相关的栏目包括):
Before update

对于每个那么我需要根据analisedatum列(仅适用于当前年份)以该行的第三个,第二个和最后一个日期更新最后三列。这需要在plaasblok相同的所有行上完成。

得到的表应该是这样的:
After update

+2

更新三列与日期?而对于一个共同的价值,原始表中的共同价值是什么?你需要显示你的数据结构或DDL。 –

+0

首先编写一个返回你想要的查询。这是否会返回你想要的部分:'SELECT Plaasblok,MIN(analiseddatum)GROUP BY Plaasblok。请指定SQL Server的版本,因为它看起来像wid夫功能会派上用场。 –

回答

0

编辑,

首先,你的结构是不是一个很好的,因为你必须在一些列具有相同价值的不同行,并不好。

更好的结构是为了处理每个plaasblok的3个最早日期。为此,您可以删除列最后secondlastthirdlastOntledings表,并创建另一个表与这些列。然后创建一个过程选择Ontledings表中的3个最古老的日期为每个plaasblokINSERT他们在新表。有了这个,你可以避免在某些列中使用具有相同值的行。

新表如下所示:

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; 
+0

谢谢蒂亚戈。我希望我的改进问题更清楚。日期不是每隔一天。 – Gideon

+0

嗨吉迪恩,看你的结构我告诉你,这不是一个好的,因为你会在一些列中有不同的行具有相同的值,并且它不好。更好的结构是为了处理每个_plaasblok_的3个最早的日期。因此,您可以从_Ontledings_表中移除_last_,_secondlast_和_thirdlast_列,并将其插入另一个列中,并创建一个过程以获取_Ontledings_表中最早的3个日期,并将它们插入到新表中,而不是更新并创建多行相同的值。 –

0

这涉及到有点自加盟在子查询中考虑多个待查日期:

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查询值 - 注意MAX日期为每个连接级联如何确保下一个最近期为止,有效期:

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 
0

下面是使用窗口功能的解决方案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