2013-10-10 2 views
2

мой 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++ 
} 

Я проверяю, сколько строк существует для данного идентификатора. Тогда мне нужно установить valid = -1 для всех строк, где n> 3;

Есть ли способ сделать это с помощью одного запроса?

+0

См: http://stackoverflow.com/questions/2334712/update-from-select-using-sql-server и http://stackoverflow.com/questions/1262786/mysql-update-query -based-on-select-query –

ответ

1

Предполагая, что (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 ; 
2
update table 
    set valid = -1 
where id in (select id 
       from table 
       where id = GIVEN_ID 
      group by id 
       having count(1) >3) 

Update: мне очень нравится решение 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

+0

Это установит 'valid' to - 1 на всех строках, где общий счет больше 3. Цикл OP сохраняет первые три строки без изменений, устанавливая 'valid' на' -1' на все после 4-й строки. – dasblinkenlight

+0

Вы правы, я пропустил эту часть – mucio

3

Вы можете использовать подзапрос в предложении WHERE, как это:

UPDATE table 
SET valid=-1 
WHERE (
    SELECT COUNT(*) FROM table tt WHERE tt.time> table.time AND tt.ID=table.ID 
) > 3 

Подзапрос подсчитывает строки с тем же идентификатором и более поздним временем. Этот счет будет три или меньше для трех последних строк; остальные будут иметь больший счет, поэтому их поле valid будет обновлено.

+0

Я получаю эту ошибку, когда я пробую это: http://stackoverflow.com/questions/45494/mysql-error-1093-cant-specify-target-table-for-update-in -из фразы –

+0

есть только 1 таблица ... –

+0

@FrancisSnipe Позвольте мне попытаться построить демо на идеоне. Какую версию MySql вы используете? – dasblinkenlight

0

сделать это для всех идентификаторов, или только один, если вы установили, где в подзапроса

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 
Смежные вопросы