0

我正在尝试使用此查询(原型)更新 tableA 中的 col1 从 tableD 获取数据:

UPDATE tableA
SET TableA.col1 = tableB.col1
FROM tableA 
INNER JOIN
    (SELECT tableC.col1, id 
     FROM
         (SELECT 
              ROW_NUMBER() OVER(PARTITION BY tableD.col1 ORDER BY (tableD.someCol desc) AS "Row Number", 
              col1, id 
          FROM tableD) tableC
     WHERE [Row Number] = 1) tableB ON tableA.id = tableB.id
WHERE 
    some_clause_on_tableA_and_tableB;

但不幸的是,这不能正常工作(更新不正确),但如果我将 tableB 的数据显式存储在 #temp 表中,然后尝试从该 #temp 表更新 tableA 则它工作正常(原型查询):

SELECT * 
INTO #temp 
FROM
    (SELECT 
         ROW_NUMBER() OVER(PARTITION BY tableD.col1 ORDER BY (tableD.someCol desc) AS "Row Number", 
         col1, id 
     FROM tableD) tableC
WHERE
    [Row Number]=1;

UPDATE tableA
SET TableA.col1 = tableB.col1
FROM tableA 
INNER JOIN #temp tableB ON tableA.id = tableB.id
WHERE some_clause_on_tableA_and_tableB;

我不知道为什么后来的作品,但首先没有。似乎在第一次查询中,两个嵌套的子查询(具有行排名)无法获取正确的数据,但我可能错了。任何帮助将不胜感激!!!

谢谢,萨钦

4

2 回答 2

2

我感觉您可能缺少使用分区和 order by 关键字对 tableD 中引用的 tableA id 进行分组的 OVER 子句。所以基本上我认为你想要做的是用tableA中每个tableA的id的第一行更新tableA中找到的每个条目。

也许尝试这样的事情作为你的 tableC 子查询

SELECT
    ROW_NUMBER() OVER (PARTITION BY tableD.fk_to_tableA order by tableD.something
    ,col1 FROM tableD

编辑以下评论

对于它的价值,这里有一个您正在尝试的查询的简单示例,它工作正常。这个例子与你的问题有什么不同?

declare @entity table (id int, latestEventId int)

declare @event table (id int, entityId int)

insert into @entity values (1, null), (2, null), (3, null), (4, null), (5, null)

insert into @event values (1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 1), (7, 2), (8, 3), (9, 4), (10, 5), (11, 1), (12, 2), (13, 3), (14, 4), (15, 5)

update tableA
    set tableA.latestEventId = tableB.id
from 
    @entity tableA
inner join
(
    select
        * 
    from 
    (
        select 
            *,
            rn = ROW_NUMBER() over (partition by e.entityId order by e.id desc)
        from
            @event e
    ) tableC
    where
        rn = 1
) tableB 
on tableB.entityId = tableA.id

-- expect the result of entity id's 1 to 5 with the values 11 to 15
select * from @entity
于 2012-05-19T20:14:22.387 回答
0

必须有一些示例未涵盖的内容。我的意思是,所提出的两种方法是等价的。但是,如果您的真实查询看起来更复杂,那可能会以某种方式阻止您看到真正的问题。

为了帮助自己更快地发现问题,您可以通过摆脱一层嵌套来简化查询:[Row Number]=1条件可以移动到主查询,如下所示:

UPDATE tableA
    SET TableA.col1 = tableB.col1
FROM tableA INNER JOIN (
    SELECT
        ROW_NUMBER() OVER(PARTITION BY tableD.col1 ORDER BY (tableD.someCol desc) AS "Row Number",
        col1,
        id
    FROM tableD
) tableB
ON tableA.id = tableB.id
WHERE some_clause_on_tableA_and_tableB
  AND tableB.[Row Number] = 1;

此外,由于您并没有真正分配新的别名,您可以从UPDATE 语句tableA的子句中省略它,如下所示:FROM

UPDATE tableA
    SET TableA.col1 = tableB.col1
FROM (
    SELECT
        ROW_NUMBER() OVER(PARTITION BY tableD.col1 ORDER BY (tableD.someCol desc) AS "Row Number",
        col1,
        id
    FROM tableD
) tableB
ON tableA.id = tableB.id
WHERE some_clause_on_tableA_and_tableB
  AND tableB.[Row Number] = 1;

从子句中省略目标表没有任何意义FROM,但是查询本身可能会变得更清晰,因此更容易发现潜在问题。

或者,正如@mouters 所建议的那样,您可以将子选择重写为公用表表达式 (CTE),或者实际上,如果tableD实际上也是子查询,则可以将其重写为一系列。考虑一下:

WITH tableB AS (
    SELECT
        ROW_NUMBER() OVER(PARTITION BY tableD.col1 ORDER BY (tableD.someCol desc) AS "Row Number",
        col1,
        id
    FROM tableD
)
UPDATE tableA
    SET TableA.col1 = tableB.col1
FROM tableA INNER JOIN tableB  /* or just: FROM tableB */
ON tableA.id = tableB.id
WHERE some_clause_on_tableA_and_tableB
  AND tableB.[Row Number] = 1;

同样,将子选择重写为 CTE 没有任何影响(在这种特殊情况下,因为您只引用 CTE 一次),但这可能(或可能不会)有助于帮助您找到问题的原因。

于 2012-05-21T20:10:17.683 回答