0

我在一个名为 Projects 的 sql server 表中有一个名为 PID 的整数字段(本质上是一个计数器),我只想在另一个字段的值更改(任务)时才增加该字段。最初,所有行的 PID=1。以下查询(我从您在其他地方的一个答案中得到)完全符合我的要求,但我需要用结果更新我的表,我无法弄清楚。

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
4

4 回答 4

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);
于 2013-10-15T04:44:17.963 回答
0

You have to return only one value from the inner query and you're looking for a rank:

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
于 2013-10-15T03:56:35.157 回答
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;

进入实际更新表格的一个。非常感谢你的支持!

于 2013-10-16T03:21:53.377 回答
0

很抱歉,但你的问题很不清楚。但是您告诉的原始 SELECT 查询对您有用,并且您想将其用于更新,我发现更新是错误的。正确的更新语法将是这样的。

使用 Task 匹配的新 Rank 更新表中的 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

在此处输入图像描述

于 2013-10-16T02:50:37.753 回答