За последние 24 часа нас посетили 23655 программистов и 1664 робота. Сейчас ищут 970 программистов ...

Стадия проектирования БД.

Тема в разделе "PHP для новичков", создана пользователем Dima4321, 5 фев 2011.

  1. Dima4321

    Dima4321 Активный пользователь

    С нами с:
    1 апр 2009
    Сообщения:
    683
    Симпатии:
    0
    Все очень просто наверно. Но я тупой.

    нужно 4 столбика. Я их сделал.

    1. ID (автоинкремент)
    2 NAME ( Имя товара) TEXT
    3 PAGE (страница описания товара) INT
    4 ABOUT (описание товара) TEXT


    Суть вот в чем. Будет так , что у товара несколько страниц описания.

    в итоге например

    присвоился id автоматом, затем вбил имя, номер страницы, и написал первое описание
    спускаюсь ниже забиваю страница №2 и пишу продолжение описания.
    в итоге присвоился на эту строчку свой id. Так и должно быть ??
    как правильно сделать выборку и правильна ли структура ??
    Может можно сделать корректней.
    Хочу пока работать с одной таблицей.
     
  2. iliavlad

    iliavlad Активный пользователь

    С нами с:
    24 янв 2009
    Сообщения:
    1.689
    Симпатии:
    4
    а какой алгоритм при разбиении описания на страницы?
     
  3. Devzirom

    Devzirom Активный пользователь

    С нами с:
    15 фев 2009
    Сообщения:
    463
    Симпатии:
    0
    Адрес:
    Пермь
    Структуры тут нет =)

    По сути ID - это id продукта, но у вас получается, что ID - это id описания =)

    Поле NAME должно быть уникальным, но у вас оно будет дублироваться

    -----------
    Я предлагаю такую структуру:

    [sql]
    CREATE TABLE `products` (
    `id` int(10) unsigned not null auto_increment,
    `name` varchar(128) not null,
    PRIMARY KEY (`id`),
    UNIQUE KEY (`name`)
    ) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1;

    CREATE TABLE `pages` (
    `id` int(10) unsigned not null auto_increment,
    `text` text,
    `number` int(10) unsigned not null,
    `product_id` int(10) unsigned not null,
    PRIMARY KEY (`id`),
    UNIQUE KEY (`number`,`product_id`)
    ) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1;[/sql]

    Данные:

    [sql]INSERT INTO `products` (`id`, `name`) VALUES ('1', 'Водка');
    INSERT INTO `products` (`id`, `name`) VALUES ('2', 'Пиво');
    INSERT INTO `products` (`id`, `name`) VALUES ('3', 'Сигареты');
    INSERT INTO `products` (`id`, `name`) VALUES ('4', 'Хлеб');

    INSERT INTO `pages` (`id`, `text`, `number`, `product_id`) VALUES ('1', 'Описание продукта \"Водка\", страница 1', '1', '1');
    INSERT INTO `pages` (`id`, `text`, `number`, `product_id`) VALUES ('2', 'Описание продукта \"Водка\", страница 2', '2', '1');
    INSERT INTO `pages` (`id`, `text`, `number`, `product_id`) VALUES ('3', 'Описание продукта \"Пиво\", страница 1', '1', '2');
    INSERT INTO `pages` (`id`, `text`, `number`, `product_id`) VALUES ('4', 'Описание продукта \"Пиво\", страница 2', '2', '2');
    INSERT INTO `pages` (`id`, `text`, `number`, `product_id`) VALUES ('5', 'Описание продукта \"Сигареты\", страница 1', '1', '3');
    INSERT INTO `pages` (`id`, `text`, `number`, `product_id`) VALUES ('6', 'Описание продукта \"Сигареты\", страница 2', '2', '3');
    INSERT INTO `pages` (`id`, `text`, `number`, `product_id`) VALUES ('7', 'Описание продукта \"Хлеб\", страница 1', '1', '4');
    INSERT INTO `pages` (`id`, `text`, `number`, `product_id`) VALUES ('8', 'Описание продукта \"Хлеб\", страница 2', '2', '4');[/sql]

    Вот что мы получили
    Код (Text):
    1. mysql> select * from products;
    2. +----+------------------+
    3. | id | name                |
    4. +----+------------------+
    5. |  1 | Водка               |
    6. |  2 | Пиво                 |
    7. |  3 | Сигареты          |
    8. |  4 | Хлеб                 |
    9. +----+------------------+
    Код (Text):
    1. mysql> select * from pages;
    2. +----+--------------------------------------------------------------------------+--------+------------+
    3. | id | text                                                                               | number | product_id |
    4. +----+--------------------------------------------------------------------------+--------+------------+
    5. |  1 | Описание продукта "Водка", страница 1                                  |      1    |          1    |
    6. |  2 | Описание продукта "Водка", страница 2                                  |      2    |          1    |
    7. |  3 | Описание продукта "Пиво", страница 1                                    |      1    |          2    |
    8. |  4 | Описание продукта "Пиво", страница 2                                    |      2    |          2    |
    9. |  5 | Описание продукта "Сигареты", страница 1                             |      1    |          3    |
    10. |  6 | Описание продукта "Сигареты", страница 2                             |      2    |          3    |
    11. |  7 | Описание продукта "Хлеб", страница 1                                    |      1    |          4    |
    12. |  8 | Описание продукта "Хлеб", страница 2                                    |      2    |          4    |
    13. +----+--------------------------------------------------------------------------+--------+------------+

    Все страницы по id продукта, id=1 - Описание продукта "Водка", страница 1 и Описание продукта "Водка", страница 2
    [sql]SELECT `name`, `text`
    FROM `products`
    INNER JOIN `pages`
    ON `product_id` = `products`.`id`
    WHERE `product_id` = '1'[/sql]

    Код (Text):
    1.  
    2. +------------+---------------------------------------------------------------------------+
    3. | name       | text                                                                                         |
    4. +------------+---------------------------------------------------------------------------+
    5. | Водка      | Описание продукта "Водка", страница 1                                  |
    6. | Водка      | Описание продукта "Водка", страница 2                                  |
    7. +------------+---------------------------------------------------------------------------+
    Страница по её id, id=4 - Описание продукта "Пиво", страница 2
    [sql]SELECT `name`, `text`
    FROM `products`
    INNER JOIN `pages`
    ON `product_id` = `products`.`id`
    WHERE `pages`.`id` = '4'[/sql]

    Код (Text):
    1. +----------+------------------------------------------------------------------+
    2. | name     | text                                                             |
    3. +----------+------------------------------------------------------------------+
    4. | Пиво     | Описание продукта "Пиво", страница 2                             |
    5. +----------+------------------------------------------------------------------+
    Страница по id продукта и номеру страницы 3-2 - Описание продукта "Сигареты", страница 2
    [sql]SELECT `name`, `text`
    FROM `products`
    INNER JOIN `pages`
    ON `product_id` = `products`.`id`
    WHERE `product_id` = '3' AND `number` = '2'[/sql]

    Код (Text):
    1. +------------------+--------------------------------------------------------------------------+
    2. | name             | text                                                                     |
    3. +------------------+--------------------------------------------------------------------------+
    4. | Сигареты         | Описание продукта "Сигареты", страница 2                                 |
    5. +------------------+--------------------------------------------------------------------------+
     
  4. Dima4321

    Dima4321 Активный пользователь

    С нами с:
    1 апр 2009
    Сообщения:
    683
    Симпатии:
    0
    Devzirom громадное громадное спасибо буду юзать наверно твой вариант. очень все подробно написано и понятно.))

    сорвал спину и пишу эти строки почти сквозь слезы..не уседеть на стуле..))

    пару дней и я сюда вернусь снова. надеюсь..

    а пока меня хавтает только на спасибо и снова в кровать..
     
  5. Devzirom

    Devzirom Активный пользователь

    С нами с:
    15 фев 2009
    Сообщения:
    463
    Симпатии:
    0
    Адрес:
    Пермь
    Не за что! И выздоравливайте!
     
  6. Dima4321

    Dima4321 Активный пользователь

    С нами с:
    1 апр 2009
    Сообщения:
    683
    Симпатии:
    0
    Вот я и ожил. ))) Начал делать рыбу по принципу, который предложил Devzirom
    Осталось несколько вопросов.

    Значит мой index приблизительной такой.

    PHP:
    1. <?php
    2.  
    3. ini_set('display_errors',1);
    4.  
    5. include('yzel.php');
    6.  
    7.  
    8.  
    9.   $sql = "SELECT `name`, `text` FROM `products`  INNER JOIN `pages` ON `product_id` = `products`.`id`
    10.  WHERE `pages`.`number` = '1'";
    11.   $data = mysql_query($sql);
    12.   echo "<table border=3>";
    13.   echo "<tr>
    14.  <th>name</th> <th>about</th></tr>";
    15.  
    16.   while($row=mysql_fetch_assoc($data))
    17.   {
    18.  
    19.   echo "<tr>";
    20.   echo '<td>';
    21.   echo $row['name'];
    22.   echo '</td>';
    23.   echo '<td>';
    24.   echo "<a href='about.php?name=$row[name]'> about $row[name]</a>";
    25.   echo '</td>';
    26.   echo "</tr>";
    27.  
    28.   }
    29.  
    30.   echo "</table>";
    31.  
    32. ?>
    вот файл about.php

    PHP:
    1. <?php
    2.  
    3. ini_set('display_errors',1);
    4.  
    5.   include('yzel.php');
    6.  
    7.   $name=$_GET['name'];
    8.  
    9.  
    10.   $sql = "SELECT `text` FROM `products`  INNER JOIN `pages` ON `product_id` = `products`.`id`
    11.  WHERE `name`='$name' AND `pages`.`number` = '1'";
    12.  
    13.  
    14.   $data = mysql_query($sql);
    15.   $row = mysql_fetch_assoc($data);
    16.   echo $row['text'];
    17.  
    18. // здесь бы надо сделать ссылку на страницу два или три в случае если они присутствуют.
    19. // что надо сделать снова запрос и проверку на empty ??
    20.  
    21.  
    22. ?>
    Короче не понимаю как организовать навигацию на страницу 2 и 3 если они присутствуют.
    empty, count .. от чего отталкиваться можно решение или направьте ??))
     
  7. tommyangelo

    tommyangelo Старожил

    С нами с:
    6 дек 2009
    Сообщения:
    2.549
    Симпатии:
    0
    Адрес:
    Мариуполь
    LIMIT нужен и гугл.
     
  8. Devzirom

    Devzirom Активный пользователь

    С нами с:
    15 фев 2009
    Сообщения:
    463
    Симпатии:
    0
    Адрес:
    Пермь
    header.php
    PHP:
    1. <?php
    2. header('Content-Type: text/html; charset=utf-8');
    3.  
    4. ini_set('display_errors', 1);
    5.  
    6. define('PRODUCTS_ON_PAGE', 10); // Количество выводимых продуктов на странице
    7.  
    8. $link = mysql_connect('localhost:3306', 'my', '_');
    9. mysql_set_charset('utf8', $link);
    10. mysql_select_db('db2', $link);
    11.  
    12. function not_found() {
    13.     header("{$_SERVER['SERVER_PROTOCOL']} 404 Not Found");
    14.     die("404 Not Found");
    15. }
    16.  
    17. ?>
    index.php
    PHP:
    1. <?php
    2. // используйте require, если инклуд-файл критичен
    3. // используйте _once, чтобы присоединить инклуд только единожды
    4.  
    5. require_once('header.php');
    6.  
    7. $part = isset($_GET['p']) ? (int) $_GET['p'] : 1;
    8.  
    9. // Получить количество записей в таблице лучше всего так:
    10. $result = mysql_query("SELECT COUNT(*) FROM `products`");
    11. $products_count = mysql_result($result, 0);
    12. mysql_free_result($result); // Желательно очищать результат
    13.  
    14. $partsNum = ($products_count) ? ceil($products_count/PRODUCTS_ON_PAGE) : 1;
    15.  
    16. // Самое время проверить, переданный в GET, параметр
    17. if($part < 1 || $part > $partsNum)
    18.     return not_found();
    19.  
    20. // не объявляйте переменные, которые используете только один раз,
    21. // избегайте слишком длинных строк,
    22. // если не используете данные поля `text`, зачем его тащить?
    23. // следите за тем, что и зачем тащите из БД.
    24.  
    25. $result = mysql_query("
    26.     SELECT `pages`.`id`, `name` FROM `products`
    27.     INNER JOIN `pages` ON `product_id` = `products`.`id`
    28.     WHERE `number` = '1'
    29.     LIMIT ".($part-1)*PRODUCTS_ON_PAGE.", ".PRODUCTS_ON_PAGE);
    30.  
    31. for($i=1; $i<$partsNum+1; $i++) {
    32.     echo( ($i == $part) ? "\n<strong>{$i}</strong>" : "\n<a href=\"?p={$i}\">{$i}</a>");
    33. }
    34.  
    35. // Большое количество операторов echo, негативно сказывается на работе скрипта
    36. // Объём разметки в большинстве случаев превышает объемы php
    37. ?>
    38. <table border="3">
    39. <tr><th>name</th><th>about</th></tr>
    40. <?php
    41. while($row = mysql_fetch_assoc($result)) {
    42. ?>
    43. <tr>
    44. <td><?php echo $row['name']; ?></td>
    45. <td><a href="about.php?id=<?php echo $row['id'] ?>">about <?php echo $row['name']; ?></a></td>
    46. </tr>
    47.  
    48. <?php }
    49. ?>
    50. </table>
    about.php
    PHP:
    1. <?php
    2. require_once('header.php');
    3.  
    4. if(!isset($_GET['id']))
    5.     return not_found();
    6.  
    7. $id = (int) $_GET['id'];
    8.  
    9. $result = mysql_query("
    10.     SELECT `pages`.`id`, `name`, `text`,
    11.         (SELECT GROUP_CONCAT(`pages`.`id`)
    12.         FROM `pages`
    13.         WHERE `product_id` = `products`.`id`
    14.         ORDER BY `number` ASC) AS `parts`
    15.     FROM `pages`
    16.     INNER JOIN `products` ON `product_id` = `products`.`id`
    17.     WHERE `pages`.`id` = '{$id}'") or die(mysql_error());
    18.  
    19. $row = mysql_fetch_assoc($result);
    20.  
    21. if(empty($row))
    22.     return not_found();
    23.  
    24. $parts = explode(',', $row['parts']);
    25.  
    26. for($i=0; $i<count($parts); $i++) {
    27.     echo( ($parts[$i] == $row['id'])
    28.         ? "\n<strong>".($i+1)."</strong>"
    29.         : "\n<a href=\"about.php?id={$parts[$i]}\">".($i+1)."</a>");
    30. }
    31.  
    32. echo "<div>{$row['text']}</div>";
    33. ?>
     
  9. Dima4321

    Dima4321 Активный пользователь

    С нами с:
    1 апр 2009
    Сообщения:
    683
    Симпатии:
    0
    Devzirom

    Да....на разбор твоего кода уйдут лучшие годы моей жизни..))

    Я сделал пока так--- достаточно колхозно и чопорно но учитывая что контент разивается маскимум на 2-4 страницы я думаю пока сойдет


    файл about.php

    PHP:
    1. <?php
    2.  
    3. ini_set('display_errors',1);
    4.  
    5.   include('yzel.php');
    6.  
    7.   $name=$_GET['name'];
    8.  
    9.  
    10.   if(!isset($_GET['n']))
    11.   {
    12.   $sql = "SELECT `text` FROM `products`  INNER JOIN `pages` ON `product_id` = `products`.`id`
    13.  WHERE `name`='$name' LIMIT 0, 1";
    14.  
    15.  
    16.  
    17.   $data = mysql_query($sql);
    18.   while($row=mysql_fetch_assoc($data))
    19.   {
    20.   echo $row['text'];
    21.   echo '<br>';
    22.   }
    23.   }
    24.   else
    25.   {
    26.   $n=$_GET['n'];
    27.   $n=($n-1);
    28.  
    29. $sql = "SELECT `text` FROM `products`  INNER JOIN `pages` ON `product_id` = `products`.`id`
    30.  WHERE `name`='$name' LIMIT $n, 1";
    31.  
    32.   $data = mysql_query($sql);
    33.   while($m=mysql_fetch_assoc($data))
    34.   {
    35.   echo $m['text'];
    36.   echo '<br>';
    37.   }
    38.   }
    39.  
    40.   $q="SELECT count(*) FROM `products`  INNER JOIN `pages` ON `product_id` = `products`.`id`
    41.  WHERE `name`='$name' ";
    42. $res=mysql_query($q);
    43. $row=mysql_fetch_row($res);
    44. $total_rows=$row[0];
    45.  
    46. $per_page=1;
    47.  
    48. $num_pages=$total_rows/$per_page;
    49.  
    50.  
    51.  
    52. $i=1;
    53.  
    54. while($i<=$num_pages)
    55. {
    56. echo "<a href='about.php?name=$name&n=$i'>page $i</a>";
    57. echo '<br>';
    58. $i++;
    59. }
    60.  
    61.  
    62.  
    63. ?>
     
  10. Dima4321

    Dima4321 Активный пользователь

    С нами с:
    1 апр 2009
    Сообщения:
    683
    Симпатии:
    0
    Кстати хотел уточнить. Я же все делаю применительно к музыке. Поэтому ситуация такова:

    Что у меня по мимо описания истории создания группы, которая будет разбиваться на несколько страниц, также и треклист где альбомов 20-30 то же будет разбиваться на 2-3 страницы. Я правильно понимаю, что тогда мне имеет смысл делать третью таблицу с такой же связкой типа `id в основной таблице будет равен product_id в третьей.

    т.е.
    1 таблица id и имя.
    2 таблица-- описание истории создания
    3 таблица -- треклист.
     
  11. BMWSauber

    BMWSauber Активный пользователь

    С нами с:
    21 ноя 2009
    Сообщения:
    151
    Симпатии:
    0
    а разве mysql varchar не имеет ограничений по размеру? т.е. как он будет туда 20 стр. запихивать? не лучше в бд хранить ссылку на файл с описанием? , да и хостеры, обычнопод, бд выделяют не очень много места.
     
  12. igordata

    igordata Суперстар
    Команда форума Модератор

    С нами с:
    18 мар 2010
    Сообщения:
    32.408
    Симпатии:
    1.768
    255 БАЙТ - варчар, в утф это даже не 255 букв...

    в тексте надо хранить текст =)

    А почему разговор зашел о варчарах? =)
     
  13. BMWSauber

    BMWSauber Активный пользователь

    С нами с:
    21 ноя 2009
    Сообщения:
    151
    Симпатии:
    0
    хз....

    но суть моего вопроса не в том, какое ограничение по размеру поля mysql пусть в "text"?
     
  14. igordata

    igordata Суперстар
    Команда форума Модератор

    С нами с:
    18 мар 2010
    Сообщения:
    32.408
    Симпатии:
    1.768
  15. Devzirom

    Devzirom Активный пользователь

    С нами с:
    15 фев 2009
    Сообщения:
    463
    Симпатии:
    0
    Адрес:
    Пермь
    Это два! Читаем документацию, делаем выводы http://dev.mysql.com/doc/refman/5.1/en/char.html
     
  16. igordata

    igordata Суперстар
    Команда форума Модератор

    С нами с:
    18 мар 2010
    Сообщения:
    32.408
    Симпатии:
    1.768
    с меня пиво. дайте пепел, я посыплю себе свои седые мудя (фото, читать далее) и пойду менять всю архитектуру моих поделок *уходит в рыданиях*

    ЗЫ: блин, прикольно, чо. Буду знать.
     
  17. Devzirom

    Devzirom Активный пользователь

    С нами с:
    15 фев 2009
    Сообщения:
    463
    Симпатии:
    0
    Адрес:
    Пермь
    [sql]CREATE TABLE `text` (
    `foo` varchar(10) not null,
    UNIQUE KEY (`foo`)
    ) ENGINE=MyISAM DEFAULT CHARSET=utf8;

    INSERT INTO `text` (`foo`) VALUES ('абвгдеёзжи');[/sql]

    Каждый символ весит 2 байта

    10 * 2 = 20 байт
     
  18. Dima4321

    Dima4321 Активный пользователь

    С нами с:
    1 апр 2009
    Сообщения:
    683
    Симпатии:
    0
    Господа ваши познания меня впечатляют )) но никто не ответил мне на вопрос.

     
  19. Gromo

    Gromo Активный пользователь

    С нами с:
    24 май 2010
    Сообщения:
    2.786
    Симпатии:
    2
    Адрес:
    Ташкент
    Dima4321
    если всего 2-3 страницы, то заводить отдельные таблицы не обязательно.
    хотя если групп планируется много, то отдельные таблицы есть гут,
    только не две отдельные, а одна и для истории, и для треклиста.
    хотя всё зависит от твоей архитектуры. как придумаешь - так и будет :)
     
  20. Dima4321

    Dima4321 Активный пользователь

    С нами с:
    1 апр 2009
    Сообщения:
    683
    Симпатии:
    0
    Gromo
    Групп будет очень много , несколько тысяч .

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

    Т.е. по факту например 3000 групп и соотвоо id

    Из них выйдет 4000-5000 страниц истории

    И 4000-6000 страниц треклистов.

    Поэтому пока и склоняюсь к 3 таблицам.
     
  21. Gromo

    Gromo Активный пользователь

    С нами с:
    24 май 2010
    Сообщения:
    2.786
    Симпатии:
    2
    Адрес:
    Ташкент
    отличное решение.

    только не храни текст истории, разбитый по страницам - храни текст в одном поле.
    удобнее редактировать, а на страницы можно и внутри пхп разбивать.

    насчёт треклистов нужно подумать - хранить их в виде хтмл можно только в случае,
    если не планируется использовать их как где-нибудь в другом виде.
     
  22. Dima4321

    Dima4321 Активный пользователь

    С нами с:
    1 апр 2009
    Сообщения:
    683
    Симпатии:
    0
    Я уже замучался. Один говорит одно другой другое. ))) Базу же не рекомендуется парсить ??. Я хочу снизить нагрузку на выборку к минимуму. Т.е. никаких меток и прочих сложных алгоритмов извлечения. Текст будет попадать в базу уже с html тегами. Редактировать в будущем ничего практически не планируется. За исключением заголовков и подобной лабуды.
     
  23. [vs]

    [vs] Суперстар
    Команда форума Модератор

    С нами с:
    27 сен 2007
    Сообщения:
    10.559
    Симпатии:
    632
    VARCHAR давно длиной 65536 байт, при чем места для поля выделяется ровно столько, сколько нужно, а не сколько задано в таблице. Но не больше заданного в таблице.
     
  24. igordata

    igordata Суперстар
    Команда форума Модератор

    С нами с:
    18 мар 2010
    Сообщения:
    32.408
    Симпатии:
    1.768
    Dima4321
    давай заново переформулируй уже на новом уровне понимания процессов. и не одной кучей текста, которую ты наложил там наверху, а по пунктам. =)

    Вобще проектирование базы надо начинать с описания "сущностей".

    А кстати все страницы первые вторые третьи десятые можно хранить в одной базе, просто поле присобачь "номер страницы"
     
  25. Gromo

    Gromo Активный пользователь

    С нами с:
    24 май 2010
    Сообщения:
    2.786
    Симпатии:
    2
    Адрес:
    Ташкент
    Dima4321