2015-12-14 106 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