Форум: Форум PHPФорум ApacheФорум Регулярные ВыраженияФорум MySQLHTML+CSS+JavaScriptФорум FlashРазное
Новые темы: 0000000
Социальная инженерия и социальные хакеры. Авторы: Кузнецов М.В., Симдянов И.В. Объектно-ориентированное программирование на PHP. Авторы: Кузнецов М.В., Симдянов И.В. C++. Мастер-класс в задачах и примерах. Авторы: Кузнецов М.В., Симдянов И.В. PHP 5/6. В подлиннике. Авторы: Кузнецов М.В., Симдянов И.В. PHP 5. На примерах. Авторы: Кузнецов М.В., Симдянов И.В., Голышев С.В.
ВСЕ НАШИ КНИГИ
Консультационный центр SoftTime

Форум MySQL

Выбрать другой форум

 

Здравствуйте, Посетитель!

вид форума:
Линейный форум Структурный форум

тема: база данных для игры
 
 автор: Valick   (04.12.2008 в 17:05)   письмо автору
 
 

Хочу сделать базу данных для игры.
Есть таблица зависимости уровня (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 в 20:42)   письмо автору
 
   для: 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)";

  Ответить  
 
 автор: Trianon   (04.12.2008 в 21:07)   письмо автору
 
   для: 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

  Ответить  
 
 автор: Valick   (04.12.2008 в 22:36)   письмо автору
 
   для: Trianon   (04.12.2008 в 21:07)
 

Так тоже пока не работает...

  Ответить  
 
 автор: Trianon   (04.12.2008 в 23:31)   письмо автору
 
   для: 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

  Ответить  
 
 автор: Valick   (04.12.2008 в 23:50)   письмо автору
 
   для: Trianon   (04.12.2008 в 23:31)
 

Да, так работает. Спасибо. Теперь бы ещё умом понять это))
Что такое ch точнее откуда оно взялось в UPDATE characters ch ?

  Ответить  
 
 автор: BinLaden   (04.12.2008 в 23:54)   письмо автору
 
   для: Valick   (04.12.2008 в 23:50)
 

Алиас

  Ответить  
 
 автор: Trianon   (04.12.2008 в 23:54)   письмо автору
 
   для: Valick   (04.12.2008 в 23:50)
 

UPDATE characters AS ch

алиас.

Больно названия у Вас кудрявые. Писать тяжело. Я и сократил.

А чтоб понять... ну так начинайте с внутреннего запроса. Он-то простой?

Дальше, для понимания, UPDATE можно заменить на SELECT * FROM , убрав строку SET .
А текст внутреннего запроса заменить на воображаемую таблицу с его результатом.

  Ответить  
 
 автор: Valick   (04.12.2008 в 23:57)   письмо автору
 
   для: Trianon   (04.12.2008 в 23:54)
 

дык там изначально небыло AS потому я и спросил)
AS можно сокращать? А то я про это нигде не вычитывал.
Спасибо теперь немного яснее.

  Ответить  
 
 автор: Trianon   (04.12.2008 в 23:59)   письмо автору
 
   для: Valick   (04.12.2008 в 23:57)
 

AS можно опускать. Этот предлог только для человека. Синтаксическим анализатором он не требуется.
Более того, насколько я помню, Oracle на него ругается и не признает.

  Ответить  
 
 автор: Valick   (05.12.2008 в 00:09)   письмо автору
 
   для: Trianon   (04.12.2008 в 23:59)
 

Вряд ли я когда-нить с Oracle увижусь))
ch и c1 для таблицы characters и l1 и l2 для таблицы level необходимы?
Т.е. без алиасов переписать этот запрос при всём желании неполучится, будет ошибка?

Ещё одна деталь. Этот запрос "лопатит" всю таблицу, я думаю это будет лишним. Его надо будет вызывать именно для того персонажа который получил очки опыта. Всем остальным (громадная часть которых оффлайн) смысла нет переписывать одно и тоже.

  Ответить  
 
 автор: Trianon   (05.12.2008 в 00:57)   письмо автору
 
   для: Valick   (05.12.2008 в 00:09)
 

тогда можно упростить как вложенный запрос, так и сам апдейт.
Впрочем, достаточно GROUP BY idc заменить на WHERE c1.id_chars = $char_id
можно еще добавить в хвост WHERE ch.id_chars = $char_id , если всё еще медлено работает.

  Ответить  
 
 автор: Valick   (05.12.2008 в 01:00)   письмо автору
 
   для: Trianon   (05.12.2008 в 00:57)
 

Уже пытаюсь это сделать) если через неделю несмогу... попрошу помочь))

  Ответить  
 
 автор: Trianon   (05.12.2008 в 01:02)   письмо автору
 
   для: Valick   (05.12.2008 в 01:00)
 

ну я ж подсказал.

  Ответить  
 
 автор: Valick   (05.12.2008 в 01:13)   письмо автору
 
   для: Trianon   (05.12.2008 в 01:02)
 

ch.id_chars = 1 это я попробовал сразу
просто хочу всё лишнее из запроса убрать

P.S. жена ругается... грит иди спать...

  Ответить  
 
 автор: Valick   (05.12.2008 в 01:55)   письмо автору
 
   для: 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";

  Ответить  
 
 автор: Trianon   (05.12.2008 в 08:31)   письмо автору
 
   для: 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

  Ответить  
 
 автор: Valick   (05.12.2008 в 09:24)   письмо автору
 
   для: Trianon   (05.12.2008 в 08:31)
 

Спасибо. Так вообще красота.
Я так понимаю WHERE ch.id_chars=$id относится и к UPDATE и к SELECT несмотря на то что последний в скобках?

Теперь остаётся объединить два запроса UPDATE (возможно?) и получится аналог триггера.

  Ответить  
 
 автор: Valick   (05.12.2008 в 09:45)   письмо автору
 
   для: 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

  Ответить  
Rambler's Top100
вверх

Rambler's Top100 Яндекс.Метрика Яндекс цитирования