Небольшой вопрос о том, как лучше записывать данные о "похожих статьях" в БД

Spear

почемучка
Небольшой вопрос о том, как лучше записывать данные о "похожих статьях" в БД

Здравствуйте, у меня к вам такой (очень важный для еня) вопрос:
на сайте есть раздел, например, статей. При добавлении новой статьи (через админку) админ выбирает статьи, которые по его мнения схожи с этой (тематика).
Так вот - похожие сатьи записываются в БД в таблицу статей в поле related(разделяются двоеточием.. например - ":5:6:7:2:12:"
получается структура таблицы сатей:

id | text | related (+всякие "дата", автор и т.п.).

Как думаете, правильно ли так записывать? То есть записывать все связанные статьи через дветочие в отдельное поле?
Спашиваю потому, что недавно скачал какую-то нуленную забугорную ЦМС - в целях обучения. Вот там и увидел что когда добавляется новая статья (или новость),
то связанные статьи (или категории, если это новость) не пишутся все в одно поле а выносятся в спец. таблицу:
номер_статьи | номер_связанной_статьи.

Как делать ПРАВИЛЬНО? как лучше?
Дело в том что при использовании второго способа - таблица с данными о похожих статьях будет очень объемная (на 1 статью в среднем 5 записей будет).

В общем не знаю как делать. Первый способ, конечно, проще для меня как для того, кто пишет код добавления - просто записать все перечисленные айди в поле.

Но с другой стороны - если люди в своей ЦМС использовали второй способ - не зря они это делали, наверное.

Помогите, пожалуйста, советом. Какой способ использовать? чем один хуже другого?
 

Krisha

pain in the neck
лучше не номера статей связывать друг с другом, а статьи привязывать к информационным рубрикам.

в любому случае, вариант - номер_статьи | номер_связанной_статьи лучше, чем - id | text | related

на вопрос почему это лучше, тебе ответит теория нормализации реляционных баз данных :)
 

Voffka

Guest
вобщето грамотней метод с отдельной таблицей но
если ты не делаеш select по "похожих статьях" то и метод "id статьи через разделитель" тоже подойдёт
по собственому опыту скажу что метод с отдельной таблицей более тормозной нежели храниение в 1 поле
 

Spear

почемучка
если ты не делаеш select по "похожих статьях"
делаю.. даже часто делаю.
То де относится и к новостям (например новости в категории 5 - select ... from news where cat like '%5%')
неправильно я так понимаю?
оки, значит буду делать отдельную таблицу.
Вот только меня беспокоит размер таблицы.. записей там будет ну ОЧЕНЬ много. Это нормально?

по собственому опыту скажу что метод с отдельной таблицей более тормозной
очень тормозит?
 

Tor

Новичок
select ... from news where cat like '%5%
метод с отдельной таблицей
подумай сам, который их методов тормознее
а если у тебя есть номера статей как 51 и 153, они тоже похожи на 5?
вообщем, вариант с отдельной страницей и правильнее идеологически и никак не медленнее и точно легче по реализации
 

440hz

php.ru
Автор оригинала: Spear
Вот только меня беспокоит размер таблицы.. записей там будет ну ОЧЕНЬ много. Это нормально?
будет тормозить будем решать как помочь, а пока делай как советуют через таблицы + индексы.
 

Spear

почемучка
440hz
Tor
Voffka
большое спасибо за ответы. Уже сделал (то есть - пока только админку, сегодня буду делать вывод пользователю)

-~{}~ 06.10.05 04:55:

возникла проблема, очень большая проблема:

если раньше, например при выведении новостей делался запрос:
select title, text, CATEGORIES from news
где CATEGORIES - номера категорий через двоеточие,
то сейчас незнаю как это реализовать.
Конечно можно делать для каждой новости отдельный запрос в таблицу отношения категорий к новостям.. но это не вариант (ведь если на странице выведится 40 новостей - это 40 лишних запросов).

Помогите, пожалуйста. немогу никак решить эту задачу :(

Таблица новостей такая:
id | title | text

таблица связи категорий с новостями:
newsID | catID

Важно то, что одна новость может относиться к нескольким категориям, так что просто вписать в основной запрос селект catID фром newsCatAsso неполучится (точнее получится, но выберится только одна категория :( )

Очень расчитываю на Вашу помощь.
Буду очень благодарен
 

nina

Новичок
SELECT n.*, c.*
FROM news AS n
INNER JOIN news_to_cats AS nc ON nc.newsID=n.id
INNER JOIN categories AS c ON c.catID=nc.catID
ORDER BY c.catID, n.id
 

Spear

почемучка
Tor
пожд новостью (статьей) пишутся категории, к которым она относится.

nina
спасибо, я попробую Ваш вариант. не было интернета почти два дня - только сейчас прочитал Ваш ответ.

-~{}~ 07.10.05 22:17:

nina
что-то неполучается.
блин :( Уже и админку переписал.. а получается что неполучается :)

никак немогу в одном запросе вывести все категории к которым относится данная новость (мне нужно вывести ТОЛЬКО айди категорий из базы newsCatAsso где поле newsID = айди новости.
Имен категорий и т.п. не нужно. Нужно только вывести все категории к которым относится данныя новостью

На всякий случай ещё раз опишу структуру базы:

1. Таблица новостей:
id | text | date
поубирал ненужное)

2. Таблица отношения новости к категории:
newsID | catID

выбор новостей идет примерно так:

$qury=select text from NEWS where date='$INPUTDATE' (например если новость за определенный день).
while ($row = $db->sql_fetch_row($query))
{
$news.= "<tr><td>$row['text']</td></td>";
}

echo $news;

конечно это схематично.
Так вот что бы показать к каким категориям относится новость я просто выбирал ещё помимо поля text поле cats (например вида ":1:34:7:").
Дльше уже это поле сравнивалось с массивом, в котором есть айди и названия всех категорий и бла-бла бла - уже идет не по теме.
Но важно то что я немогу сейчас одним махов узнать к каким категориям относится новость.
Очень нужна Ваша помощь. Ничего немогу придумать..
 

Steamroller

Новичок
Spear, примерно так:
SELECT news.id, text, date, GROUP_CONCAT(categories.catID ORDER BY categories.catID SEPARATOR ':') FROM news, news_to_categories WHERE news.id=news_to_categories.newsID GROUP BY news.id, text, date;

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

Spear

почемучка
Но это неправильный подход.
Ты говоришь что у тебя массив есть, с помощью которого ты для новости будешь получать список категорий для новости в нужном виде.
Правильнее этот список для новости получать из базы. При наличии нужных индексов выполняться будет мгновенно практически.
ты говоришь про список категорий?
Ну массив-то естевственно составляется не в ручную а из базы берется,

а массив - потому что иначе никак не сделать.

но не в названиях категорий дело и т.п.

дело в том что бы достать категории к которым относится новость. Все остальное уже сделано и работает великолепно.

Народ, а ещё у меня такой вопрос - а зачем, блин, я все-таки сделал другую систему учета отношения новостей к категориям (по совету) НО, блин, теперь немогу эти новости нормально вывести, а если и получится, то не слишком ли тяжелные запросы получаются?
Стоит одно другого?
У меня уже блин... нервы здают...
 

Steamroller

Новичок
дело в том что бы достать категории к которым относится новость. Все остальное уже сделано и работает великолепно.
Так я тебе и написал выше, каким запросом это достается.
Народ, а ещё у меня такой вопрос - а зачем, блин, я все-таки сделал другую систему учета отношения новостей к категориям (по совету) НО, блин, теперь немогу эти новости нормально вывести, а если и получится, то не слишком ли тяжелные запросы получаются?
Стоит одно другого?
У меня уже блин... нервы здают...
По-моему не стоит. То есть если переделывать, то надо делать целиком правильно. А так в итоге и ты намучаешься, и скрипт всё равно кривой останется. :)
 

Spear

почемучка
если переделывать, то надо делать целиком правильно
дык я хочу правильно. По идее первую часть (хранение соотношения новости к категории) сделал правильно - в отдельной таблице,
и вот сейчас пробую сделать правильно вывод категорий.
Было бы лечге если бы новость могла быть только в одной категории. Хотя тогда и смысла нет в отдельной таблице.

-~{}~ 08.10.05 00:33:

Steamroller
неполучается твоим способом.
я чего-то не пойму - он вообще получается выбирает еёщ и адйи всех категорий, зачем? блин, ужасЪ (всмысле настроение)
немогу сделать несчастный модель новостей. ррррр....

-~{}~ 08.10.05 00:35:

Steamroller
если не сложно - помоги все-таки настроить мой запрос под твой. Я его не понимаю немного..

вот мой запрос:

$sql= "select title, time, text from news ORDER BY sid DESC";
$result = $db->sql_query($sql);
while ($row = $db->sql_fetchrow($result))
{
......
}
 

Steamroller

Новичок
Если я правильно понял задачу, то ты хочешь вывести список новостей, и для каждой новости - список категорий, к которым новость принадлежит (в виде названий, ссылок на разделы сайта, неважно в общем).
Правильные варианты такие:
1) одним запросом выбираем новости, начинаем их выводить, для каждой новости - из базы отдельным запросом достаем список категорий
2) одним запросом выбираем новости сразу уже с готовым списком категорий для каждой (в том виде, в котором это выводится)

В общем-то при небольшом объеме пофиг как делать, можно и так как ты хочешь, собрать сначала массив, потом с его помощью делать что-то.
Но на приличном объеме - подойдет только вариант 1.

-~{}~ 08.10.05 00:46:

Автор оригинала: Spear
Steamroller
если не сложно - помоги все-таки настроить мой запрос под твой. Я его не понимаю немного..

вот мой запрос:

$sql= "select title, time, text, sid from news ORDER BY sid DESC";
$result = $db->sql_query($sql);
while ($row = $db->sql_fetchrow($result))
{
......
}
ну вот там где у тебя .... делаешь что-то типа:

echo "<h2>$row[title] - $row[time]</h2><p>$row[text]</p>";
$sql2 = "select catID from news_to_categories where newsID=$row[sid]";
$res2=$db->sql_query($sql2);
while($row_cat=$db->sql_fetchrow($res2) {
echo "<a href='/categ.php?cid=$row_cat[catID]'>$names[catID]</a>";
}


(я у тебя в твой запрос sid добавил).
 

Spear

почемучка
Steamroller
для каждой новости - список категорий, к которым новость принадлежит в виде названий, ссылок на разделы сайта, неважно в общем).
нет. мне нужно ля каждой новости ТОЛЬКО БЛИН АЙДИШНИКИ. ТОЛЬКО. Только айдишники из таблицы news_to_cats. все. Айдишники, только айдишники и ничего кроме айдишников. Формировать из них ссылки, названия и прочую лабуду мне не нужно. Совершенно. Тут не нужно. Это делается немного дальше по скрипту, но не относится к теме разговора совсем. никак.


считаем запросы в БД, учтем что сам движок уже делает 5 (например). Предположим что пользователь выводит 40 новостей на старницу.

одним запросом выбираем новости, начинаем их выводить
раз.

для каждой новости - из базы отдельным запросом достаем список категорий
сорок

итого все-го то каких-то несчастных 46 запросов в базу.
так я мог с самого начала сделать.
Мне же важна минимальная нагрузка

пс
твой запрос не заработал. как я его не крутил.


ппс
появилась такая гребаная идея:
сначала делаю запрос в базу, составляя массив которы будет содержать "айди новости":"айди всех категорий"
 

Voffka

Guest
Spear постучи в icq 489286 я тебе дам всё готовое как я на 700mb.ru сделал а именно
- похожие публикации
- 1 публикация в нескольких категориях
- 1 категория в нескольких над / под категориях
сделано без всяких хитроумных join итд - наглядно и проверено временем , нагрузка никакая
а то тут бдут ещё неделю тебя понимать а потом ты понимать предложеное решение
 

Steamroller

Новичок
твой запрос не заработал. как я его не крутил.
Это который с group_concat?

итого все-го то каких-то несчастных 46 запросов в базу.
так я мог с самого начала сделать.
Мне же важна минимальная нагрузка
Ну так делай.
При этом варианте как раз будет минимальная нагрузка.
Ты видимо полагаешь, что чем больше запросов к базе, тем больше нагрузка. Так вот это на самом деле не так. В данном случае - как раз мелкими запросами быстрее, чем одним большим.
 

Spear

почемучка
Ты видимо полагаешь, что чем больше запросов к базе, тем больше нагрузка. Так вот это на самом деле не так. В данном случае - как раз мелкими запросами быстрее, чем одним большим
ну а если таких новостей 200?
Ведь я такой способ хочу использовать и для статей. И пользователь может вывести спмсок из 200 статей, где будет указана статья и категории статьи.
Это не дело.

-~{}~ 08.10.05 01:04:

Voffka
спасибо! Стучу :)
 

Steamroller

Новичок
ну а если таких новостей 200?
Ведь я такой способ хочу использовать и для статей. И пользователь может вывести спмсок из 200 статей, где будет указана статья и категории статьи.
Это не дело.
Да ну и что, что 200.
Запрос вида "select catID from news_to_categories where newsID=константа" на однопроцессорном P4 может отдаваться порядка 2 тысяч раз в секунду, причем размер базы практически пофиг.
А вот запрос, в котором сразу собираются категории для каждой записи, может и до секунды легко дорасти, и причем с ростом базы он будет расти нелинейно.

Ну да ладно, раз раз Voffka тебе даст готовое решение, предлагаю на этом тему закрыть. :)
 
Сверху