2014-01-27 4 views
0

У меня есть таблица с записями, как показано ниже:MySQL: Итерация и обновление записей в таблице

USER | STATUS 
-------------- 
user1 | 1 
user2 | 1 
user1 | 1 
user2 | 1 
user1 | 0 
user2 | 1 
user3 | 1 

Я хочу добавить поле COUNT и обновить таблицу, так что COUNT будет иметь значения, как показано ниже:

USER | STATUS | COUNT 
---------------------- 
user1 | 1  | 1 
user2 | 1  | 1 
user1 | 1  | 2 
user2 | 1  | 2 
user1 | 0  | NULL # Don't want to update where STATUS=0 
user2 | 1  | 3 
user3 | 1  | 1 

Я не знаю много о хранимых процедурах, и те, которые я пробовал, на самом деле не дали результат, который я хочу.

Очень ценится, если кто-то может мне помочь. Благодаря!

+0

Если таблица не имеет ПК, он будет недетерминирована итерировать его, если он не заблокирован! –

+0

У него есть первичный ключ - и auto increment id. Я просто не показывал его, потому что хочу обновить на основе значений поля USER. – shyam

ответ

1

Если у вас есть столбец ID, вы можете использовать запрос ниже (вы должны добавить столбец с названием prevUser, то вы можете оставить этот столбец после)

ALTER TABLE users ADD COLUMN prevUser varchar(50); 
SET @prevUser = ''; 
SET @count = 0; 
UPDATE users 
SET count = (@count:=IF(@prevUser != user,1,@count+1)), 
    prevUser = (@prevUser := user) 
WHERE status != 0 
ORDER BY user,id; 
ALTER TABLE users DROP COLUMN prevUser; 

sqlFiddle

2

Нет необходимости в хранимой процедуре. Я добавил столбец auto_increment, иначе он был бы недетерминированным.

Образец данных:

CREATE TABLE t 
    (id int auto_increment primary key, `USER` varchar(5), `STATUS` int) 
; 

INSERT INTO t 
    (`USER`, `STATUS`) 
VALUES 
    ('user1', 1), 
    ('user2', 1), 
    ('user1', 1), 
    ('user2', 1), 
    ('user1', 0), 
    ('user2', 1), 
    ('user3', 1) 
; 

ALTER TABLE t ADD COLUMN COUNT int default null; 

Запрос:

UPDATE t 
INNER JOIN (
    SELECT 
    id, 
`USER`, `STATUS`, 
CASE WHEN (@my_count := IF(@prevUser != USER, 1, @my_count + 1)) IS NULL THEN NULL 
WHEN (@prevUser := USER) IS NULL THEN NULL 
ELSE @my_count END AS `COUNT` 
FROM 
t, 
(SELECT @my_count := 0, @prevUser := NULL) init 
WHERE 
STATUS != 0 
ORDER BY USER, id 
) sq ON sq.id = t.id 
SET t.COUNT = sq.COUNT; 

Результат:

| ID | USER | STATUS | COUNT | 
|----|-------|--------|--------| 
| 1 | user1 |  1 |  1 | 
| 2 | user2 |  1 |  1 | 
| 3 | user1 |  1 |  2 | 
| 4 | user2 |  1 |  2 | 
| 5 | user1 |  0 | (null) | 
| 6 | user2 |  1 |  3 | 
| 7 | user3 |  1 |  1 | 
  • увидеть его работы вживую в sqlfiddle
+0

Это именно то, что я хочу! Однако он не работает так, как ожидалось, в моем ящике MySQL. При этом счет постепенно увеличивается, независимо от того, изменяется ли значение USER. То есть для приведенного выше примера ID = 2 имеет COUNT = 2, ID = 3 имеет COUNT = 3 и так далее. Моя MySQL-версия - 5.6.14-62.0-log. – shyam

+0

Ну, это работает и для меня в 5.6.6, как вы можете видеть здесь: http://sqlfiddle.com/#!9/dbef1/1/0 Вы что-то изменили? Например, удалили 'ORDER BY'? – fancyPants

+0

Нет. Я не изменил запрос (конечно, используя фактические имена таблиц и полей). – shyam

0

версия без использования переменных сеанса

ALTER TABLE users ADD COLUMN `count` INT; 

UPDATE users u JOIN 
(
    SELECT id, 
    (
    SELECT 1 + COUNT(*) 
     FROM users 
    WHERE user = t.user 
     AND id < t.id 
) count 
    FROM users t 
    WHERE status = 1 
) q 
    ON u.id = q.id 
    SET u.count = q.count 

Результат:

 
| ID | USER | STATUS | COUNT | 
|----|-------|--------|--------| 
| 1 | user1 |  1 |  1 | 
| 2 | user2 |  1 |  1 | 
| 3 | user1 |  1 |  2 | 
| 4 | user2 |  1 |  2 | 
| 5 | user1 |  0 | (null) | 
| 6 | user2 |  1 |  3 | 
| 7 | user3 |  1 |  1 | 

Вот SQLFiddle демо

Смежные вопросы