LINUX.ORG.RU

Правильный Mysql запрос

 


0

1

Здравствуйте. Помогите пожалуйста решить проблемку. Есть две таблицы в одной базе, table1 и table2. В table1 поле valid = 1, как приплюсовать запросом эту единицу в table2 в поле valid? Но есть нюанс. В table1 выборку по полю id а в table2 по полю store. То есть надо как то правильно плюсануть из поля valid таблицы table1 по id в поле valid таблицы table2 по полю store. Спасибо.



Последнее исправление: lucky_Star (всего исправлений: 2)

Примерно так:

select t1.valid+t2.valid fron t1 {какой-то} join t2 on t1.id=t2.store

Точный запрос зависит от твоих конкретных нужд, которые ты не указал, но там уж сам как-нить разберёшься. Скорее всего ты не знал про join'ы а теперь знаешь.

firkax ★★★★★
()
Последнее исправление: firkax (всего исправлений: 1)
Ответ на: комментарий от lucky_Star
UPDATE t2 SET valid = valid + COALESCE((SELECT valid FROM t1 WHERE id = t2.store), 0);

COALESCE для того, чтобы в случае, когда для t2.store нет соответствующего t1.id, не произошло SET valid = valid + NULL, ибо результат такой операции: valid = NULL.

Darth_Revan ★★★★★
()
Последнее исправление: Darth_Revan (всего исправлений: 1)
Ответ на: комментарий от lucky_Star
MariaDB [test]> CREATE TEMPORARY TABLE t1 (id BIGINT PRIMARY KEY AUTO_INCREMENT, valid INTEGER NOT NULL);
Query OK, 0 rows affected (0,102 sec)

MariaDB [test]> CREATE TEMPORARY TABLE t2 (store BIGINT UNIQUE KEY NOT NULL, valid INTEGER NOT NULL);
Query OK, 0 rows affected (0,072 sec)

MariaDB [test]> INSERT INTO t1 (valid) VALUES (1), (1), (0), (1), (1);
Query OK, 5 rows affected (0,001 sec)
Records: 5  Duplicates: 0  Warnings: 0

MariaDB [test]> INSERT INTO t2 (store, valid) VALUES (1, 4), (2, 2), (3, 1), (4, 0), (6, 42);
Query OK, 5 rows affected (0,001 sec)
Records: 5  Duplicates: 0  Warnings: 0

MariaDB [test]> UPDATE t2 SET valid = valid + COALESCE((SELECT valid FROM t1 WHERE id = t2.store), 0);
Query OK, 3 rows affected (0,001 sec)
Rows matched: 5  Changed: 3  Warnings: 0

MariaDB [test]> SELECT * FROM t2;
+-------+-------+
| store | valid |
+-------+-------+
|     1 |     5 |
|     2 |     3 |
|     3 |     1 |
|     4 |     1 |
|     6 |    42 |
+-------+-------+
5 rows in set (0,001 sec)

Оно делает всё, что я и ожидаю.

Darth_Revan ★★★★★
()
Ответ на: комментарий от crutch_master

Мне нужно чтобы этот запрос

UPDATE t2 SET valid = valid + COALESCE((SELECT valid FROM t1 WHERE store = t2.id), 0);
Работал больше чем с одной строкой. Когда в таблице t2 появляется еще одна строка то выдает ошибку
Ошибка в запросe (1242): Subquery returns more than 1 row
То есть с 1 строкой все отлично работает и плюсует куда надо, но дело в том что там строчки прибавляются и перестает работать. Я ставил LIMIT 1 но тогда делает операцию только с первой строкой а остальные игнорирует. Мне надо бы чтобы все поля считала и плюсовала а их там неограниченное кол-во может быть

lucky_Star
() автор топика
Ответ на: комментарий от Darth_Revan

Ещё я должен отметить, что в общем случае то, который t1.store будет выбран, фактически определяется лишь тем, который физически лежит ближе к началу. В InnoDB это будет наименьшее значение в случае, если t1.store – это основной ключ, потому что clustered index.
В общем, для однозначности нужно написать так:

UPDATE t2 SET valid = valid + COALESCE((SELECT valid FROM t1 WHERE store = t2.id ORDER BY store LIMIT 1), 0);

Если желателен, наоборот, последний t1.store, тогда ORDER BY store DESC LIMIT 1.

Darth_Revan ★★★★★
()
Последнее исправление: Darth_Revan (всего исправлений: 1)
Ответ на: комментарий от Darth_Revan

Спасибо за дополнение очень важное! Я тут подумал, что после этого запроса можно же другим запросом обнулять поле valid и я попробовал вручную обнулил и нормально. Костыль кончено но пока сойдет. Там есть еще нюансы интересные до которых постепенно дойду. Спасибо за помощь!

lucky_Star
() автор топика
Ответ на: комментарий от Darth_Revan

А как правильно дописать в запрос, или новый запрос который следом пойдет, чтобы ставило 0 в t1 в поле valid после того как единичку от туда дернет и плюсанет в t2?

lucky_Star
() автор топика
Ответ на: комментарий от Darth_Revan

Я сейчас на это смотрю и понимаю, что совет с ORDER BY не имеет никакого смысла, потому что в выборке по определению все store одинаковые, и сортировать их по store глупо. Тут нужно по identity column сортировать.

Darth_Revan ★★★★★
()
Ответ на: комментарий от lucky_Star

Как-то так:

START TRANSACTION;
UPDATE t2 SET valid = valid + COALESCE((SELECT valid FROM t1 WHERE store = t2.id ORDER BY id LIMIT 1), 0);
UPDATE t1 SET valid = 0 WHERE id IN (SELECT MIN(id) FROM t1 GROUP BY store);
COMMIT;

Но есть нюанс, и он ровно в том, что нужен identity в t1, чтобы можно было отличить те кортежи/поля, из которых значения были взяты, от тех, откуда не были.

Вообще, если нужно их вообще все взять из t1 и записать в t2, то вот это, как раз, сделать легко:

START TRANSACTION;
UPDATE t2 SET valid = valid + COALESCE((SELECT SUM(valid) FROM t1 WHERE store = t2.id GROUP BY store), 0);
UPDATE t1 SET valid = 0;
COMMIT;
Darth_Revan ★★★★★
()
Последнее исправление: Darth_Revan (всего исправлений: 2)
Ответ на: комментарий от Darth_Revan

Спасибо все работает идеально!

START TRANSACTION;
UPDATE t2 SET valid = valid + COALESCE((SELECT SUM(valid) FROM t1 WHERE store = t2.id GROUP BY store), 0);
UPDATE t1 SET valid = 0;
COMMIT;
Очень помогли спасибо!

lucky_Star
() автор топика