|
|
|
| Хочу сделать базу данных для игры.
Есть таблица зависимости уровня (level) персонажа от набранного опыта (exp):
--
-- Структура таблицы `level`
--
CREATE TABLE `level` (
`level` int(11) default NULL,
`exp` int(11) default NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
--
-- Дамп данных таблицы `level`
--
INSERT INTO `level` VALUES (0, 0);
INSERT INTO `level` VALUES (1, 200);
INSERT INTO `level` VALUES (2, 400);
INSERT INTO `level` VALUES (3, 800);
INSERT INTO `level` VALUES (4, 1600);
INSERT INTO `level` VALUES (5, 2400);
INSERT INTO `level` VALUES (7, 4800);
INSERT INTO `level` VALUES (8, 9600);
INSERT INTO `level` VALUES (9, 19200);
INSERT INTO `level` VALUES (10, 38400);
|
Значения в этой таблице могут измениться в любой момент и зависят только от моей прихоти и здравого смысла.
Вторая таблица содержит характеристики персонажа
--
-- Структура таблицы `characters`
--
CREATE TABLE `characters` (
`id_chars` int(11) NOT NULL auto_increment,
`level` int(11) default NULL,
`exp` int(11) default NULL,
PRIMARY KEY (`id_chars`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=1 ;
|
За выполнение задания или по какой-либо другой причине персонаж получает опыт (количество неограничено, да и вообще может быть отрицательным).
Соответственно этот опыт прибавляется к значению поля exp таблицы characters и в зависимости от количества опыта необходимо вычислить уровень персонажа в соответствии с таблицей level и записать в поле level таблицы characters.
Вопрос: как это грамотно реализовать без участия РНР, т.е. одним запросом или может нужно как-то связать эти таблицы, что предпочтительнее, и делать это всё автоматически при изменении значения exp таблицы characters.
Структура таблиц (да и вообще всего подлежит корректировке)
P.S. Поискал по форуму и скорее всего здесь необходимо использовать триггер. | |
|
|
|
|
|
|
|
для: Valick
(04.12.2008 в 17:05)
| | Так как триггеры с версии 5.0.2, то попробовал составить запрос
Так работает:
$query="SELECT `level.level`
FROM `characters`,`level`
WHERE characters.id_chars = 1 AND level.exp > characters.exp
LIMIT 0,1";
|
А вот так нет:
$query="UPDATE `characters`
SET characters.level =
(SELECT `level.level`
FROM `characters`,`level`
WHERE characters.id_chars = 1 AND level.exp > characters.exp
LIMIT 0,1)";
|
| |
|
|
|
|
|
|
|
для: Valick
(04.12.2008 в 20:42)
| | а так?
UPDATE characters ch
JOIN
(
SELECT MIN(l1.exp) AS mxp, c1.id_chars AS idc
FROM characters c1 JOIN level l1 ON c1.exp >= l1.exp
GROUP BY idc
) AS s1 ON ch.id_chars = s1.idc
JOIN level l2 ON s1.mxp=l2.exp
SET ch.level = l2.level
|
| |
|
|
|
|
|
|
|
для: Trianon
(04.12.2008 в 21:07)
| | Так тоже пока не работает... | |
|
|
|
|
|
|
|
для: Valick
(04.12.2008 в 22:36)
| | тогда так
UPDATE characters AS ch
JOIN
(
SELECT MAX(l1.exp) AS mxp, c1.id_chars AS idc
FROM characters AS c1 JOIN level AS l1 ON c1.exp >= l1.exp
GROUP BY idc
) AS s1 ON ch.id_chars = s1.idc
JOIN level AS l2 ON s1.mxp=l2.exp
SET ch.level = l2.level
|
| |
|
|
|
|
|
|
|
для: Trianon
(04.12.2008 в 23:31)
| | Да, так работает. Спасибо. Теперь бы ещё умом понять это))
Что такое ch точнее откуда оно взялось в UPDATE characters ch ? | |
|
|
|
|
|
|
|
для: Valick
(04.12.2008 в 23:50)
| | Алиас | |
|
|
|
|
|
|
|
для: Valick
(04.12.2008 в 23:50)
| | UPDATE characters AS ch
алиас.
Больно названия у Вас кудрявые. Писать тяжело. Я и сократил.
А чтоб понять... ну так начинайте с внутреннего запроса. Он-то простой?
Дальше, для понимания, UPDATE можно заменить на SELECT * FROM , убрав строку SET .
А текст внутреннего запроса заменить на воображаемую таблицу с его результатом. | |
|
|
|
|
|
|
|
для: Trianon
(04.12.2008 в 23:54)
| | дык там изначально небыло AS потому я и спросил)
AS можно сокращать? А то я про это нигде не вычитывал.
Спасибо теперь немного яснее. | |
|
|
|
|
|
|
|
для: Valick
(04.12.2008 в 23:57)
| | AS можно опускать. Этот предлог только для человека. Синтаксическим анализатором он не требуется.
Более того, насколько я помню, Oracle на него ругается и не признает. | |
|
|
|
|
|
|
|
для: Trianon
(04.12.2008 в 23:59)
| | Вряд ли я когда-нить с Oracle увижусь))
ch и c1 для таблицы characters и l1 и l2 для таблицы level необходимы?
Т.е. без алиасов переписать этот запрос при всём желании неполучится, будет ошибка?
Ещё одна деталь. Этот запрос "лопатит" всю таблицу, я думаю это будет лишним. Его надо будет вызывать именно для того персонажа который получил очки опыта. Всем остальным (громадная часть которых оффлайн) смысла нет переписывать одно и тоже. | |
|
|
|
|
|
|
|
для: Valick
(05.12.2008 в 00:09)
| | тогда можно упростить как вложенный запрос, так и сам апдейт.
Впрочем, достаточно GROUP BY idc заменить на WHERE c1.id_chars = $char_id
можно еще добавить в хвост WHERE ch.id_chars = $char_id , если всё еще медлено работает. | |
|
|
|
|
|
|
|
для: Trianon
(05.12.2008 в 00:57)
| | Уже пытаюсь это сделать) если через неделю несмогу... попрошу помочь)) | |
|
|
|
|
|
|
|
для: Valick
(05.12.2008 в 01:00)
| | ну я ж подсказал. | |
|
|
|
|
|
|
|
для: Trianon
(05.12.2008 в 01:02)
| | ch.id_chars = 1 это я попробовал сразу
просто хочу всё лишнее из запроса убрать
P.S. жена ругается... грит иди спать... | |
|
|
|
|
|
|
|
для: Trianon
(05.12.2008 в 01:02)
| | Вот так у меня получилось:
$query="UPDATE characters AS ch
JOIN
(
SELECT MAX(level.level) AS level
FROM characters JOIN level ON characters.exp >= level.exp AND characters.id_chars=$id
) AS s1 ON ch.id_chars=$id
SET ch.level = s1.level";
|
| |
|
|
|
|
|
|
|
для: Valick
(05.12.2008 в 01:55)
| |
UPDATE characters AS ch
SET ch.level = ( SELECT MAX(level.level) FROM level WHERE ch.exp >= level.exp )
WHERE ch.id_chars=$id
|
| |
|
|
|
|
|
|
|
для: Trianon
(05.12.2008 в 08:31)
| | Спасибо. Так вообще красота.
Я так понимаю WHERE ch.id_chars=$id относится и к UPDATE и к SELECT несмотря на то что последний в скобках?
Теперь остаётся объединить два запроса UPDATE (возможно?) и получится аналог триггера. | |
|
|
|
|
|
|
|
для: Valick
(05.12.2008 в 09:24)
| | Вот так нормально?
UPDATE characters AS ch
SET ch.exp = ch.exp + $up, ch.level = ( SELECT MAX(level.level) FROM level WHERE ch.exp >= level.exp )
WHERE ch.id_chars=$id
|
| |
|
|
|