Надежда С.
349 повідомлень
#10 років тому
Здравствуйте, уважаемые гуру.
Сломала мозг себе за ночь. Я совсем почти не разбираюсь в mysql, но нужно составить запрос.

Есть таблица variable. В нем столбцы name и value

1. Нам нужны записи, начинающиеся в name на mymoney
2. Далее у этих записей в столбце value необходимо проверить условие >= 10 (чтобы не зайти в минус)
3. Если удовлетворяет условиям, то вычитаем 10

Попробовала составить запрос, но не получилось:
UPDATE `variable` (`name`, `value`) SET `value` = `value` -10 where `value` LIKE 'mymoney%' AND `value` > 9;


Этот запрос собираюсь выполнять раз в день по крону, чтобы списывать 10 единиц ежедневно у всех пользователей. (mymoney1 - средства пользователя1, mymoney2 - средства пользователя2 и т.д.)

Еще вопрос. Что за символы в данных, типа i: и s:? информации в интернете не смогла найти по этим символам, потому что даже не знаю как это сформулировать.
Дмитрий С.
10 повідомлень
#10 років тому
Эти символы указывают на сериализованные данные (php function i:integer, s:string)

MySQL не умеет десериализовывать поэтому value > 9 не срабатывает (вы сравниваете строку с целым)
используйте регулярку для отбора значений (то есть целой части поля value)
..where REGEXP '.*i:+.*'

После этого, выбранные значения можно положить во временную таблицу
Синтаксис может быть таким
CREATE TEMPORARY TABLE IF NOT EXISTS table2 AS (SELECT * FROM table1)

Затем, примените update (декремент) к выборке

На самом деле, средствами SQL получается слишком хитровы..анно
В общем, нужно сначала десериализовать данные
Артем Л.
11416 повідомлень
#10 років тому
Примерно так:

$db->q("SELECT * FROM `variable` WHERE `value` LIKE 'mymoney%'");
$res = $db->result();
foreach ($res as $r) {в цикле десериализовать данные и сравнить с 10, провести апдейты.}

Надежда С.
349 повідомлень
#10 років тому
Hungry_Hunter, Спасибо! Только целый час ломала голову, почему не работает. Оказалось у вас опечатка. Надо name вместо value 
Андрей Халецкий
3562 повідомлення
#10 років тому
Ну или прочитать про вложенные запросы, для конкретно этой задачи скорее всего разницы не почувствуете, но все же.
Артем Л.
11416 повідомлень
#10 років тому
Цитата (WebAir):
Оказалось у вас опечатка. Надо name вместо value

Да, да, надо name )
Надежда С.
349 повідомлень
#10 років тому
Вот что в результате написала. Спасибо всем, кто не был равнодушен. Если есть предложения по оптимизации или где то что то не так сделала, пишите
$query = "SELECT * FROM `variable` WHERE `name` LIKE 'mymoney%'"; 
$res = mysql_query($query);
while($row = mysql_fetch_array($res)){
$value = unserialize($row);
if ($value >= 10) {
$vychet = $value - 10;
mysql_query("UPDATE `variable` SET `value`='".serialize($vychet)."' WHERE `name`='".$row."'");
}
}
Артем Л.
11416 повідомлень
#10 років тому
Можно на всякий случай в строке 7 сделать intval
А в 13 строке заменить условие на WHERE id = $row, если у вас есть он, будет работать быстрее.
Надежда С.
349 повідомлень
#10 років тому
Hungry_Hunter, в вопросах денег стоит ли пользоваться intval? Копейки нельзя списывать с счетов ))
id нету, только столбцы name и value
Это Drupal...
Александр Ж.
575 повідомлень
#10 років тому
В вопросах денег хорошо бы использовать pdo, prepared statements и транзакции
Артем Л.
11416 повідомлень
#10 років тому
Цитата (WebAir):
в вопросах денег стоит ли пользоваться intval? Копейки нельзя списывать с счетов ))

А, ну если там дробные могут быть, то, конечно не нужно.
Вообще деньги лучше хранить в int а потом умножать/делить на 100. Т.е. сумму вида 120 руб 15 коп хранить в виде 12015, тогда операции будут делаться быстрее и не будет проблем с округлением типа float.
Василий С.
402 повідомлення
#10 років тому
Цитата (Hungry_Hunter):
Вообще деньги лучше хранить в int а потом умножать/делить на 100. Т.е. сумму вида 120 руб 15 коп хранить в виде 12015, тогда операции будут делаться быстрее и не будет проблем с округлением типа float.
Ух ты! Думал, я один такой) Когда только начинал, мы в небольшой веб-конторе именно так и делали. Потом посчитал что это "исторически сложилось" и из-за незнания типа decimal. Оказывается, до сих пор в тренде )) Эхх, олдскульный, тепло-ламповый подход 
Андрей Халецкий
3562 повідомлення
#10 років тому
Цитата (Hungry_Hunter):
Вообще деньги лучше хранить в int а потом умножать/делить на 100.
А можно еще почитать и использовать decimal :-D
UPD. Ну вот, чукча не читатель - чукча писатель, но пусть будет.
Артем Л.
11416 повідомлень
#10 років тому
Цитата (tarakan_):
из-за незнания типа decimal.

Цитата (SmartDesign):
А можно еще почитать и использовать decimal :-D


Когда-то тоже выбирал что использовать, вот эти аргументы убедили меня в использовании типа int.

Минусы:

- При неаккуратной работе (не через bcmath) можно ошибиться при умножении или делении
- Работа через bcmath медленее
- У разной валюты разное кол-во знаков поле запятой — если у вас мультивалютная система, будет избыточность данных. Придется делать более 2 знаков после запятой, но они будут нужны не всем
Андрей Халецкий
3562 повідомлення
#10 років тому
Когда я слышу "медленее" и "избыточно" сразу задаю вопрос о числах.
Я вообще сильно сомневаюсь что внутри хранение децимала держит избыточные знаки если они не заданы, но даже если так это даже мельче чем экономия на спичках. Про скорость - вообще молчу, на фоне выборки из базы и перебора значений в ПХП - это точно мизер.

Что до ошибки в умножении или делении - не совсем понимаю о чем речь, работа с деньгами и так и так штука особенная =)
Артем Л.
11416 повідомлень
#10 років тому
SmartDesign, c decimal не сравнивал, но int по сравнению с float работает быстрее в 6 раз
Андрей Халецкий
3562 повідомлення
#10 років тому
Децимал - это инт со смещением ;-)
работает "в 6 раз быстрее" - это какой-то рекламный лозунг, о какой "работе" идет речь?
Артем Л.
11416 повідомлень
#10 років тому
<?php
$a = 1.2;
$b = 3.4;
for ($i=0;$i<1000000;$i++) {$c = bcdiv($a,$b,2);}

<?php
$a = 11.2;
$b = 3.4;
$a *= 100;
$b *= 100;
for ($i=0;$i<1000000;$i++) {$c = $a/$b; $c *= 100; $c = (int)$c; $c /= 100;}

Время работы первого 3,49 секунды, второго 0.57 секунды
Андрей Халецкий
3562 повідомлення
#10 років тому
Не касаясь вопроса методологии измерения и аналогичности операций: выигрыш в 3 секунды на одним миллионе операций это правильное приложений усилий?
что до методологии - почему домножение на 100 вынесено из цикла?
Роман Беляев
16382 повідомлення
#10 років тому
Php и Mysql в этой задаче выглядят забавно
А давайте везде поменяем двойные кавычки на одинарные?