2013-06-06 144 views
3

我有兩個表:如何使用生成多行的select語句更新表?

[Table container] 
id int 
<some more fields> 
latest_measurement int 

[Table measurement] 
id int 
container_id int 
unixtime bigint 

現在我想根據從測量表測量的最新更新傳感器表latest_measurement列。我已經準備了子查詢每sensor_id返回最新的測量和這個作品:

SELECT m.fill_level 
from measurement m 
inner join (
    select m.container_id, MAX(m.unixtime) as maxdate from measurement m GROUP BY container_id 
) m2 
on m2.container_id = m.container_id 
where m.unixtime = m2.maxdate 

但是,如果我再在我的更新語句中使用此查詢,如下所示時,出現異常:

UPDATE container 
SET latest_fill_level = (
    SELECT m.fill_level 
    from measurement m 
    inner join (
     select m.container_id, MAX(m.unixtime) as maxdate from measurement m GROUP BY container_id 
) m2 
    on m2.container_id = m.container_id 
    where m.unixtime = m2.maxdate 
    and container.id = m.container_id) 

最後,這裏的例外:

Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression. 

如何編寫可以從SELECT語句塔更新各自的價值多行的更新語句t產生多個值?

+0

你能提供多少記錄呢你內心的查詢結果? ('select m.fill_level from ...') –

回答

2

您的子查詢不會斷開關係。如果最近的unixtime有多個測量結果,它將返回多行。由於SQL Server無法知道應該使用哪一行來更新列,因此會引發Subquery returned more than 1 value.錯誤。

你可以使用row_number()打破平局:

update c 
set  latest_measurement = m.fill_level 
from container c 
join (
     select row_number() over (
        partition by container_id 
        order by unixtime desc) as rn 
     ,  * 
     from measurement 
     ) m 
on  c.id = m.container_id 
     and m.rn = 1 -- Latest measurement only 

或者,你可以打破與top 1條款的關係:

update container 
set  latest_measurement = 
     (
     select top 1 fill_level 
     from measurement m 
     where container.id = m.container_id 
     order by 
       unixtime desc 
     ) 
+0

好吧,我想我明白了。但我需要做的是更新容器表中的所有行以重新創建最新的測量值。我可以用SQL查詢來做到這一點,或者沒有辦法繞過程序嗎? –

+0

這兩個查詢都會更新'container'表中的所有行。嘗試一下 – Andomar

+0

Andomar,告訴我第二種模式的名稱:更新與相關的子查詢? –

相關問題