2013-10-15 51 views
0

我有一個稱爲PID的SQL服務器表中稱爲PID的整數字段(本質上是一個計數器),我只想在另一個字段的值更改(任務)時增量。對於所有行,最初PID = 1。以下查詢(我從其中一個答案中得到的)完全符合我的要求,但我需要用結果更新我的表格,而且我無法弄清楚。只有當另一個字段更改值時,如何增加SQL Server數據庫表中的整數字段?

SELECT Task, 
    dense_rank() over(order by Task) PID 
FROM dbo.Projects; 

如果我這樣做

Update Projects 
SET Projects.PID =(SELECT Task, 
    dense_rank() over(order by Task) PID 
FROM dbo.Projects); 

我得到「的選擇列表的INSERT語句包含比插入列表中的項目。SELECT值的數目必須與INSERT列的數目相匹配。 「我怎樣才能更新我的表與查詢,讓我想要什麼?

這是表設計:

CREATE TABLE [dbo].[Projects] 
( 
    [PID] [int] NULL 
    , [TID] [int] IDENTITY(1,1) NOT NULL 
    , [Project] [nvarchar](127) NOT NULL 
    , [Task] [nvarchar](127) NOT NULL 
    , [Dollars] [decimal](18, 0) NOT NULL 
    , [TaskLead] [nvarchar](127) NULL 
) ON [PRIMARY]; 

我填充表

INSERT INTO dbo.Projects(Project, Task, Dollars, TaskLead) 
SELECT Project + ' ' + ProjectDescription, Task + ' ' + TaskDescription, Dollars, TaskLead 
FROM TM1_1 
ORDER BY Project ASC, Task ASC; 

例如數據:

PID  TID  Project  Task 
1  1  Prj1  Tsk11 
1  2  Prj1  Tsk12 
2  1  Prj2  Tsk21 

我想更新表,使所有相同的項目具有相同的PID。我現在想:

use mbt_tm1; 
;WITH cteRank AS (
    SELECT PID, DENSE_RANK() OVER (PARTITION BY Project ORDER BY Project ASC) AS Calculated_Rank 
    FROM Projects) 
UPDATE cteRank 
SET PID = Calculated_Rank 
+0

你需要更清楚你實際需要什麼。與其他任務相比,你希望'PID'列是它的'Task'的'dense_rank()'嗎?請注意,該數字將根據「任務」列的排序順序進行上/下。 –

+0

我只知道使用dense_rank的查詢工作。我要的是更新我的臺,使得我得到的,例如, – user2093192

+0

例如, PID TID項目任務 11 Prj1 Tsk11 1 2 Prj1 Tsk12 2 1 Prj2 Tsk21 等。我從另一個來源獲得Prj's和Tsk's。我需要根據這種模式添加PID和TID。我不附於dense_rank。我只知道當我在查詢中使用它時,它做了我想要的。 – user2093192

回答

0

你必須從內部查詢返回只有一個值,你正在尋找一個排名:

Update Projects 
SET Projects.PID = X.Calculated_Rank 
FROM Project P 
INNER JOIN 
    (SELECT P1.PID, DENSE_RANK() OVER (PARTITION BY P1.Project ORDER BY P1.Project ASC) AS Calculated_Rank 
    FROM Projects P1) X 
ON X.PID = P.PID 
+0

不幸的是,我得到: 「Msg 512,Level 16,State 1,Line 2 子查詢返回的值不止一個,當子查詢跟隨=,!=,<, <= , >,> =或子查詢爲用作表達式 該聲明已被終止。「 我想我需要一種不同的方法,但我不確定那是什麼。 – user2093192

+0

我認爲你想要最大的價值,對吧? – Szymon

+0

檢查我的編輯是否有效。 – Szymon

0

不知道更多關於你的具體問題,這也許會工作?

Update Projects 
SET Projects.PID = dense_rank() over(order by Task); 

爲了解決您的問題,我將一些小樣本放在一起,我想這些小樣本會顯示您的要求。如果這不能反映您的環境,請爲您的問題添加詳細信息。

CREATE TABLE Projects 
(
    ProjectID INT 
    , Task INT 
    , PID INT 
); 
GO 

INSERT INTO Projects (ProjectID, Task, PID) VALUES (1, 1, 1); 
INSERT INTO Projects (ProjectID, Task, PID) VALUES (2, 1, 2); 
INSERT INTO Projects (ProjectID, Task, PID) VALUES (3, 1, 3); 
INSERT INTO Projects (ProjectID, Task, PID) VALUES (4, 2, 1); 

UPDATE Projects 
SET Projects.PID = (
    SELECT MAX(PID) + 1 
    FROM Projects p 
    WHERE P.Task = Projects.Task 
); 

SELECT * 
FROM Projects; 

[編輯#2]

除非我誤解你的要求,這似乎是一個簡單的方法來更新PID所有相關項目:

UPDATE Projects 
SET PID = (SELECT MAX(PID) FROM Projects P WHERE P.Project = Projects.Project); 
+0

可惜沒有,我得到: 「消息4108,級別15,狀態1,行2 窗函數只能出現在SELECT或ORDER BY子句。」 也許我需要用遊標來做到這一點,但我對遊標並不熟悉。 – user2093192

+0

我可以幫你解決這個問題,但是如果你編輯你的問題來顯示實際的表格設計,以及一些樣品數據行和樣品所需的結果,它確實會對我有所幫助。 –

+0

這裏是表格設計: USE [MBT_TM1] GO /******對象:表[dbo]。[Projects] Script Date:2013/10/15 19:03:51 ***** */ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO CREATE TABLE [DBO]。[項目]( \t [PID] [INT] NULL, \t [TID] [INT] IDENTITY(1,1)NOT NULL, \t [項目] [nvarchar的](127)NOT NULL, \t [任務] [nvarchar的](127)NOT NULL, \t [幣] [十進制](18,0)NOT NULL, \t [TaskLead] [nvarchar](127)NULL )ON [PRIMARY] – user2093192

0

遺憾地說,但你的問題很不明確。但你所說的原始SELECT查詢正在爲你工作,而你想用它來更新,我發現這個更新是錯誤的。 正確的更新syntex會是這樣的。

更新表中的PID,其中任務匹配的新等級。

UPDATE t1 SET t1.Projects.PID = t2.pid 
    FROM Projects t1 
    JOIN 
    ( 
     SELECT Task ,DENSE_RANK() OVER (ORDER BY Task) PID 
     FROM Projects 
    )t2 
    ON t1.Task=t2.task 

編輯:-1 該查詢得到的輸出爲你解釋和示例所示。

不需要使用CTE。

set nocount on 
    declare @prj table 
    (
     pid  int null 
     ,tid int null 
     ,prj sysname 
     ,tsk sysname 

    ) 
    insert into @prj (prj,tsk) 
    select 'prj1','tsk11' 
    union all select 'prj1','tsk12' 
    union all select 'prj2','tsk21' 
    union all select 'prj2','tsk22' 

    update t1 set t1.pID=t2.pID, t1.tID=t2.tID 
    from @prj t1 
    join 
    (

     select dense_RANK() over (order by prj) as pID 
       ,ROW_NUMBER() over (partition by prj order by prj,tsk) as tID 
       ,prj,tsk 
     from @prj 
    )t2 
     on t1.prj=t2.prj and t1.tsk=t2.tsk 

    select * from @prj 

enter image description here

+0

我的情況是完全一樣的在http://www.sqlservercentral.com/Forums/Topic1020106-338-1.aspx但什麼工作的那個人是不是爲我工作。我非常感謝幫助。 – user2093192

+0

根據需要更新了查詢。不需要CTE。請參閱編輯1下的代碼。 –

+0

CTE似乎工作得很好。有沒有理由不使用它? – user2093192

0

這是什麼工作:

;WITH cte AS (
    SELECT PID, 
     DENSE_RANK() OVER (
     ORDER BY Project ASC) AS Calculated_Rank 
    FROM Projects 
) 
UPDATE cte SET PID = Calculated_Rank 

它轉化一個查詢,顯示的結果,即:

SELECT Project, 
    dense_rank() over(order by Project) PID 
FROM dbo.Projects; 

成一個實際更新的表。非常感謝你的支持!

相關問題