我的DB有这样的结构:
ID | text | time | valid
这是我目前的代码。我正试图找到一种方法来做这个查询。
rows = select * from table where ID=x order by time desc;
n=0;
foreach rows{
if(n > 3){
update table set valid = -1 where rows[n];
}
n++
}
我正在检查给定ID存在多少行。然后我需要为n> 3;
的所有行设置valid = -1有没有办法用一个查询来做到这一点?
答案 0 :(得分:3)
您可以在WHERE
子句中使用子查询,如下所示:
UPDATE table
SET valid=-1
WHERE (
SELECT COUNT(*)
FROM table tt
WHERE tt.time > table.time
AND tt.ID = table.ID
) > 3
子查询计算具有相同ID和更晚时间的行。对于最近的三行,此计数将为三或更少;其余的将有更多的计数,因此他们的valid
字段将被更新。
答案 1 :(得分:2)
update table
set valid = -1
where id in (select id
from table
where id = GIVEN_ID
group by id
having count(1) >3)
更新:我真的很喜欢dasblinkenlight的解决方案,因为它非常整洁,但我想尝试以我的方式做到这一点,这是一个相当冗长的解决方案:
update Table1
set valid = -1
where (id, time) in (select id,
time
from (select id,time
from table1
where id in (select id
from table1
group by id
having count(1) >3)
-- and id = GIVEN_ID
order by time
limit 3, 10000000)
t);
同样在SQLFiddle
答案 2 :(得分:2)
假设(id,time)
有一个UNIQUE
约束,即没有两行具有相同的id
和相同的time
:
UPDATE
tableX AS tu
JOIN
( SELECT time
FROM tableX
WHERE id = @X -- the given ID
ORDER BY time DESC
LIMIT 1 OFFSET 2
) AS t3
ON tu.id = @X -- given ID again
AND tu.time < t3.time
SET
tu.valid = -1 ;
答案 3 :(得分:0)
为所有ID执行此操作,或者仅在您在子查询中设置位置时执行一次
UPDATE TABLE
LEFT JOIN (
SELECT *
FROM (
SELECT @rn:=if(@prv=id, @rn+1, 1) AS rId,
@prv:=id AS id,
TABLE.*
FROM TABLE
JOIN ( SELECT @prv:=0, @rn:=0 ) tmp
ORDER BY id, TIMESTAMP
) a
WHERE rid > 3
) ordered ON ordered.id = TABLE.id
AND ordered.TIMESTAMP = TABLE.TIMESTAMP
AND ordered.text = TIMESTAMP.text
SET VALID = -1
WHERE rid IS NOT NULL