|
|
|
| Задача достаточно специфическая.
Есть 3 таблицы
users
posts
throws
Причем на одну запись из posts соответствует 1 запись из таблицы users и несколько записей из таблицы throws.
Вот когда было не несколько а одна, то было все замечательно, и я обходился таким запросом.
$sql = "SELECT u.*, p.*, th.*
FROM post p, users u, throws th
WHERE p.topic_id = $topic_id
AND u.user_id = p.poster_id
AND th.topic_id = $topic_id
ORDER BY p.post_time
LIMIT $start, ".$board_config['posts_per_page'];
|
$topic_id - номер темы
После того, как th.topic_id и $topic_id перестало соответствовать 1:1 все полетело к чертям.
Если раньше я получал 2-х мерный массив, где кол-во столбцов было как и запрашивалось (LIMIT) то сейчас из стало больше (ровно в столько, сколько записей в throws соответствует на один topic_id)
2-x мерный массив я получал так:
if ($row = $db->sql_fetchrow($result))
{
do
{
$postrow[] = $row;
}
while ($row = $db->sql_fetchrow($result));
$db->sql_freeresult($result);
$total_posts = count($postrow);
}
|
Как мне поступить? Я даже не могу разбить этот запрос на 2. Ведь я не знаю, сколько мне надо записей из throws (а лишь только - начальный и конечный id_topic для них)
А может быть можно было бы получить 3-х мерный массив? | |
|
|
|
|
|
|
|
для: Artem S.
(30.10.2004 в 16:09)
| | Хм... какая задача - вам нужны только пользователи (user), соотвествующие топики (post) и любой (throws)? В этом случае можно сгруппировать результат по пользователям
$sql = "SELECT u.*, p.*, th.*
FROM post p, users u, throws th
WHERE p.topic_id = $topic_id
AND u.user_id = p.poster_id
AND th.topic_id = $topic_id
ORDER BY p.post_time
GROUP BY u.user_id
LIMIT $start, ".$board_config['posts_per_page'];
|
Как и раньше будете получать 1 throws на 1 user.
Или всё-таки нужны все throws - для каждого пользователя? В чём тогда сложность - в выводе на страницу? | |
|
|
|
|
|
|
|
для: Artem S.
(30.10.2004 в 16:09)
| | Можно загнать дополнительный запрос в цикл обработки
<?php
mysql_query(...); // первый запрос
do
{
mysql_query("select * from throws where user_id=".$row[0]); // второй запрос
} while (...)
?>
|
А полученный массив от второго запроса упаковать в строку при помощи serialize() и сунуть в качестве дополнительного параметра $postrow[].
Такой подход потребует дополнительных запросов на каждом цикле и это может быть неприемлемо, тогда можно не группировать значения, а проверять каждый результат, не имеет ли он одинаковых полей - u.user_id (сортировать следует ORDER BY p.post_time, u.user_id), если значение этого поля равно значению предыдущего цикла - продолжать формировать дополнительный массив для упаковки serialize(), если нет - создаём новый элемент массива $postrow[].
PS Так можно свернуть трёх-мерный массив в двумерный, а вообще можно обойтись и без упаковки-распаковки действительно воспользовавшись трёхмерным массивом.
http://www.softtime.ru/forum/read.php?id_forum=3&id_theme=535&page=1 | |
|
|
|
|
|
|
|
для: cheops
(30.10.2004 в 16:42)
| | >> Или всё-таки нужны все throws - для каждого пользователя? В чём тогда сложность - в выводе на страницу?
ДА
Ну если выводить сообщения то они выводятся так.
[сообщение_1]
> Имя 1
> Сообщение 1
> Throw 1
......
[сообщение_1]
> Имя 1
> Сообщение 1
> Throw 2
......
[сообщение_2]
> Имя 2
> Сообщение 2
> Throw 3
......
Сообщения дублируются. А мне надо чтобы все throw для этого сообщения вывелись через запятую
[сообщение_1]
> Имя 1
> Сообщение 1
> Throw 1, Throw 2
$postrow[] увеличился и все превратилось хз во что. И как все распихать по массивам я не понимаю.
2-ой Вариант меня не устаивает так как будит сильно увеличена нагрузка на базу.
Может подскажете как организовать из этого запроса 3-х мерный массив. | |
|
|
|
|
|
|
|
для: Artem S.
(30.10.2004 в 17:22)
| | Хм... ну примерно, нужно двигаться в следующем направлении
<?php
$id_user = -1; // Инициализируем значением, которого нет в таблицах
$i = -1; // Счётчик
while ($row = $db->sql_fetchrow($result));
{
if($id_user == $row['user_id'])
{
// Если user_id равен значению предыдущего цикла
// продолжаем формировать третье измерение массива
$postrow[$i]['throw'][] = $row['throw_id'];
}
else
{
++$i;
$postrow[$i] = $row;
$postrow[$i]['throw'][] = $row['throw_id'];
}
}
$db->sql_freeresult($result);
$total_posts = count($postrow);
?>
|
| |
|
|
|
|
|
|
|
для: cheops
(30.10.2004 в 18:04)
| | у меня тоже хитрый запрос. надо выбрать из таблицы четыре последних баннера с признаком top. но расположить их не в порядке выборки, а в порядке, указанном в поле banner_ord. я делаю запрос
$query = "SELECT * FROM banner_main WHERE pos = 'top' ORDER BY id DESC LIMIT 0,3";
|
где мне еще раз отсортировать выбранные баннеры по полю banner_ord, ведь у меня уже есть в запросе ORDER BY id? | |
|
|
|
|
|
|
|
для: elenaki
(05.11.2004 в 13:48)
| | А по id тоже нужно сортировать? Если нет, то можно воспользоваться запросом:
$query = "SELECT * FROM banner_main WHERE pos = 'top' ORDER BY banner_ord DESC LIMIT 0,3";
|
| |
|
|
|
|
|
|
|
для: cheops
(05.11.2004 в 14:57)
| | по id я сортирую, потому что мне нужно 4 послeдних баннера. т.к. id=autoincrement, то по DESC id мне выберутся 4 последних. если можно как-то по-другому выбирать четыре баннера с наибольшими id, то потом, конечно, можно сортировать по banner_ord.... | |
|
|
|
|
|
|
|
для: cheops
(05.11.2004 в 14:57)
| | Так а id (я так понял) используется для сортировки чтобы вывести 4 последних значения.
О как можно! Придумал.
Ставьте не LIMIT 0,3 , а LIMIT [количество строк], [количество строк -4]
Тогда Ваша сортировка ORDER BY будет работать именно для сортировки. Т.е. ORDER BY banner_ord | |
|
|
|
|
|
|
|
для: glsv (Дизайнер)
(05.11.2004 в 15:08)
| | Точнее:
LIMIT [количество строк-4], [количество строк]
|
| |
|
|
|
|
|
|
|
для: glsv (Дизайнер)
(05.11.2004 в 15:10)
| | а можно узнать количество строк в базе, не делая дополнительный запрос? | |
|
|
|
|
|
|
|
для: elenaki
(05.11.2004 в 15:30)
| | Функция count() должна в любой части запроса работать
$query = "SELECT * FROM banner_main WHERE pos = 'top' ORDER BY banner_ord DESC LIMIT COUNT(*)-4,3";
|
| |
|
|
|
|
|
|
|
для: cheops
(05.11.2004 в 15:36)
| | SELECT * FROM banner_main WHERE pos = 'top' ORDER BY banner_ord DESC LIMIT COUNT(*)-4,3 failed!
You have an error in your SQL syntax near 'COUNT(*)-4,3' at line 1 | |
|
|
|
|
|
|
|
для: elenaki
(05.11.2004 в 15:48)
| | Да... вложенная таким образом агрегатная функция может и не работать. | |
|
|
|
|
|
|
|
для: glsv (Дизайнер)
(05.11.2004 в 16:09)
| | Ну в любом случае, MySQL не сканирует таблицы, а хранит число записей в таблице, поэтому дополнительный запрос будет выполняться очень быстро. | |
|
|
|
|
|
|
|
для: cheops
(05.11.2004 в 21:14)
| | хорошо, я сделаю дополнительный запрос, узнаю, сколько у меня записей в таблице и возьму 4 с конца (поначалу там может быть и меньше 4-х записей). спасибочки. :) | |
|
|
|
|
|
|
|
для: elenaki
(05.11.2004 в 13:48)
| | Да, хитрый запрос.
Вам фактически нужно 2 раза сортировать. Первый раз для выборки и второй только для, собственно, сортировки.
Учитывая, что в третьей версии MySQL подзапросов еще нет, то... наверное одним запросом это не сделать. А сортировать уже выборку. Хорошо что она хоть не большая - всего 4 позиции. | |
|
|
|