Как вывести в сумме N записей из двух таблиц с постраничной навигацией?
Всем привет! Есть две таблицы (абсолютно разные), но мне нужно вывести их в одну ленту.
Я делаю один запрос к одной таблице и получаю записи, потом ко второй и на стороне php сортирую их по дате.
Как сделать так, чтобы получилось скажем 20 записей в сумме? Ведь может получится так, что с одной таблицы сегодня есть 20 записей, а с другой нету вообще.
В голову пока пришло только такое решение: выбирать из каждой таблицы столько записей, сколько нужно получить в результате, потом отсортировать по дате и с обрезать массив с помощью array_slice() до этого количества.
Может есть еще какие-то решения? Ведь если мне нужно будет вывести записи на второй странице - уже что-то таким способом не получается совсем
Нужна третья, агрегирующая таблица, в которую писать связи с вашими двумя таблицами при их заполнении. Таблица, например, с полями "target" (писать идентификатор связи, например table1), "target_id" - id записи (в ваших таблицах) и полем "date_pub", в которое писать дату. При получении данных делать выборку из этой таблицы и присоединять ваши две таблицы по связям. Соответственно на связующих ячейках должен быть индекс (составной на два поля target_id и target) и индекс на поле date_pub для сортировки.
Теперь я совсем запутался ))
просто не так давно задавал вопрос по этому поводу и мне посоветовали делать разными запросами и совмещать их...
Вот есть у нас таблица `agregate` у нее поля `target` (таблица) и `target_id` (id в таблице)
как в таком случае составить запрос? У меня не получается определить таблицу, которую присоединять.
SELECT agregate.* FROM `agregate` LEFT JOIN ????? ON svyazi.`target_id` = ?????.`id`
Получается такой запрос... Но что подставлять на место вопросиков? Логично подставить значение поля agregate.`target` в котором хранится название таблицы которую хотим приджойнить... но как?
Незачем из неё выбирать, она нужна только для связей. В select пишите то, что хотите выбрать из ваших таблиц. В случае совпадения названий полей позаботьтесь о префиксах.
SELECT one.*, two.field_name as two_field_name
FROM agregate i
INNER JOIN one_table as one ON one.id = i.target_id AND i.target = 'one_table'
INNER JOIN two_table as two ON two.id = i.target_id AND i.target = 'two_table'
one_table и two_table - это те самые ваши таблицы. Ну и я предположил, что в ваших таблицах есть уникальные поля id с авто инкрементом например. Для простоты выбираем из первой таблицы все ячейки SELECT one.* с их оригинальными названиями. Со второй таблицы придётся перечислить поля для выборки, назначив им алиасы, если такие названия полей есть в первой таблице.
Fuze: спасибо! А новые записи в эту таблицу добавлять на этапе добавления записей в остальные?
И еще один вопросик пожалуйста... На стороне php проверять из какой таблицы конкретная запись, стОит по какому-то полю, которое есть в одной таблице но нет в другой? Вроде if(is_null($row['one_id'])) // значит это вторая таблица
> А новые записи в эту таблицу добавлять на этапе добавления записей в остальные
Да. Добавили запись в одну из основных таблиц - добавили запись в agregate.
> На стороне php проверять из какой таблицы конкретная запись, стОит по какому-то полю, которое есть в одной таблице но нет в другой? Вроде if(is_null($row['one_id'])) // значит это вторая таблица
Это уже какая у вас итоговая задача, например, разные шаблоны вывода для разных записей. Тут уже как вам удобнее/необходимо.
Также, можно выбирать записи только из таблицы agregate (без джойнов) - формировать список id записей. А после в два запроса выбрать по списку id из двух таблиц через IN (id1, id2, ...). По производительности, при наличии индексов в таблицах, не проиграете.
если кто-то будет это читать...
Поправлю пример, который Fuze привел во втором комментарии:
Вместо INNER JOIN нужен LEFT JOIN. Иначе не найдет никаких данных