У меня есть страница, которая отображает список проектов. В каждом проекте отображаются следующие данные, извлеченные из базы данных mysqli:
Проекты отображаются 6 страниц с использованием системы разбиения на страницы
Поскольку это основано на моем старом проекте, он был изначально выполнен с неаккуратным кодом (я просто учился и не знал ничего лучшего), используя много запросов. Три, фактически, только для пунктов 5-7, и они содержались внутри цикла while, который работал с системой разбиения на страницы. Теперь я прекрасно понимаю, что это даже близко к тому, чтобы быть правильным способом заниматься бизнесом.
Я знаком с INNER JOIN и использованием подзапросов, но я обеспокоен тем, что я не могу получить все эти данные, используя только один запрос выбора по следующим причинам:
Элементы 1-4 достаточно просты с базовым запросом SELECT
, НО …
Пункт 5 нуждается в SELECT COUNT
AND …
Пункт 6 требует базового запроса SELECT
с ORDER by RAND LIMIT 1
чтобы выбрать одно случайное фото из всех, связанных с каждым проектом (с использованием FilesystemIterator не может быть и речи, потому что в таблице фотографий есть столбец, указывающий 0, если фотография неактивна и 1, если он активен)
Пункт 7 выбирается из таблицы перекрестных ссылок для тегов и проектов и таблицы, содержащей идентификатор и имена тегов
Учитывая это, я не уверен, что все это может (даже если это важно) выполнить только с одним запросом или если потребуется несколько запросов. Я неоднократно читал, как стоит писать на носу газету, чтобы вложить один или несколько запросов внутри цикла while. Я даже читал, что несколько запросов – это, в общем, плохая идея.
Поэтому я застрял. Я понимаю, что это может показаться слишком общим, но у меня нет никакого кода, который работает, а только старый код, который использует 4 запроса для выполнения задания, 3 из которых вложены в цикл while.
Структура базы данных ниже.
Таблица проектов:
+-------------+---------+----------+---------------+------+ | project_id | title | subtitle | description | part | |---------------------------------------------------------| | 1 | Chevy | Engine | Modify | 1 | | 2 | Ford | Trans | Rebuild | 1 | | 3 | Mopar | Diff | Swap | 1 | +-------------+---------+----------+---------------+------+
Фотографий таблица:
+----------+------------+--------+ | photo_id | project_id | active | |--------------------------------| | 1 | 1 | 1 | | 2 | 1 | 1 | | 3 | 1 | 1 | | 4 | 2 | 1 | | 5 | 2 | 1 | | 6 | 2 | 1 | | 7 | 3 | 1 | | 8 | 3 | 1 | | 9 | 3 | 1 | +----------+------------+--------+
Таблица тегов:
+--------+------------------+ | tag_id | tag | |---------------------------| | 1 | classic | | 2 | new car | | 3 | truck | | 4 | performance | | 5 | easy | | 6 | difficult | | 7 | hard | | 8 | oem | | 9 | aftermarket | +--------+------------------+
Таблица перекрестных ссылок тегов / проектов:
+------------+-----------+ | project_id | tag_id | |------------------------| | 1 | 1 | | 1 | 3 | | 1 | 4 | | 2 | 2 | | 2 | 5 | | 3 | 6 | | 3 | 9 | +------------+-----------+
Я не прошу, чтобы код был написан для меня, но если то, что я прошу, имеет смысл, я искренне ценю толкание в правильном направлении. Часто я борюсь с руководствами PHP и MySQLi в Интернете, поэтому, если есть способ разбить это, то фантастический.
Большое спасибо всем вам.
Вы можете делать подзапросы внутри предложения SELECT
, например:
SELECT p.title, p.subtitle, p.description, p.part, (SELECT COUNT(photo_id) FROM Photos where project_id = p.project_id) as total_photos, (SELECT photo_id FROM Photos where project_id = p.project_id ORDER BY RAND LIMIT 1) as random_photo FROM projects as p
Теперь, для списка тегов, поскольку он возвращает более одной строки, вы не можете сделать подзапрос, и вы должны сделать один запрос для каждого проекта. Ну, на самом деле вы можете, если вы вернете все теги в какой-то конкатенации, например, в список с разделителями-запятыми: tag1, tag2, tag3 … но я не рекомендую в этот раз вам разбить значение столбца , Делайте это только в том случае, если у вас много проектов, а производительность для получения списка тегов для каждого отдельного проекта довольно низкая. Если вы действительно этого хотите, вы можете:
SELECT p.title, p.subtitle, p.description, p.part, (SELECT COUNT(photo_id) FROM Photos where project_id = p.project_id) as total_photos, (SELECT photo_id FROM Photos where project_id = p.project_id ORDER BY RAND LIMIT 1) as random_photo, (SELECT GROUP_CONCAT(tag SEPARATOR ', ') FROM tags WHERE tag_id in (SELECT tag_id FROM tagproject WHERE project_id = p.project_id)) as tags FROM projects as p
Как вы сказали из пункта 1 – 4, у вас уже есть решение.
Добавьте к тому же запросу SQL_CALC_FOUND_ROWS
вместо SELECT COUNT
чтобы решить элемент 5.
Для элемента 6 вы можете использовать подзапрос или, возможно, LEFT JOIN
ограничивающий один результат.
Для последнего элемента вы также можете использовать подзапрос, соединяющий все теги в одном результате (например, через запятую).