Могут ли таблицы SELECT, SELECT COUNT и перекрестные ссылки обрабатываться одним запросом?

У меня есть страница, которая отображает список проектов. С каждым проектом отображаются следующие данные, полученные из базы данных mysqli:

  1. заглавие
  2. подзаголовок
  3. Описание
  4. Номер детали (1 из х)
  5. Общее количество фотографий, связанных с этим проектом
  6. Случайно выбранная фотография из проекта
  7. Список тегов

Проекты отображаются 6 на страницу с использованием системы нумерации страниц

Поскольку это основано на моем старом проекте, изначально оно было сделано с неаккуратным кодом (я только учился и не знал ничего лучше), используя много запросов. Три, фактически, только для пунктов 5-7, и они содержались в цикле while, который работал с системой нумерации страниц. Теперь я прекрасно понимаю, что это даже не то, что нужно для ведения бизнеса.

Я знаком с INNER JOIN и использованием подзапросов, но меня беспокоит, что я не смогу получить все эти данные, используя только один запрос select, по следующим причинам:

  • Пункты 1-4 достаточно просты с базовым SELECT запрос, НО …

  • Пункт 5 нуждается в SELECT COUNT А ТАКЖЕ…

  • Пункт 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, поэтому, если есть какой-то способ разобраться в этом, то это фантастика.

Большое спасибо всем вам.

3

Решение

Вы можете делать подзапросы внутри вашего 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
3

Другие решения

Как вы сказали в пунктах 1-4, у вас уже есть решение.

Добавить к тому же запросу SQL_CALC_FOUND_ROWS вместо SELECT COUNT решить пункт 5.

Для пункта 6 вы можете использовать подзапрос или может быть LEFT JOIN ограничение до одного результата.

Для самого последнего элемента вы также можете использовать подзапрос, объединяющий все теги в один результат (например, через запятую).

1

По вопросам рекламы [email protected]