2010-10-27 2 views
2

Я пытаюсь написать запрос, чтобы получить информацию о курсах, а также количество заказов и посетителей. У каждого курса может быть много заказов, и в каждом бронировании может быть много участников.Быстрый комплексный запрос для выбора заказов

У нас уже есть рабочий отчет, но он использует несколько запросов для получения требуемой информации. Один, чтобы получить курсы, один, чтобы получить заказы, и один, чтобы получить количество участников. Это очень медленно, потому что размер базы данных вырос.

Есть целый ряд дополнительных условий для докладов:

  • Бронирование должно быть сделано более 5 минут назад, или были подтверждены
  • Бронирование не должно быть отменено
  • Курс не должны быть помечены как удаленные
  • Место и место проведения курсов должны быть LIKE строка поиска
  • Курсы без заказов должны быть указаны в Результаты

Это структура таблицы: (Я опустил ненужную информацию. Все поля не являются нулевыми и не имеют значения по умолчанию)

mysql> DESCRIBE first_aid_courses;

+------------------+--------------+-----+----------------+ 
| Field   | Type   | Key | Extra   | 
+------------------+--------------+-----+----------------+ 
| id    | int(11)  | PRI | auto_increment | 
| course_date  | date   |  |    | 
| region_id  | int(11)  |  |    | 
| location   | varchar(255) |  |    | 
| venue   | varchar(255) |  |    | 
| number_of_spaces | int(11)  |  |    | 
| deleted   | tinyint(1) |  |    | 
+------------------+--------------+-----+----------------+ 

mysql> DESCRIBE first_aid_bookings;

+-----------------------+--------------+-----+----------------+ 
| Field     | Type   | Key | Extra   | 
+-----------------------+--------------+-----+----------------+ 
| id     | int(11)  | PRI | auto_increment | 
| first_aid_course_id | int(11)  |  |    | 
| placed    | datetime  |  |    | 
| confirmed    | tinyint(1) |  |    | 
| cancelled    | tinyint(1) |  |    | 
+-----------------------+--------------+-----+----------------+ 

mysql> DESCRIBE first_aid_attendees;

+----------------------+--------------+-----+----------------+ 
| Field    | Type   | Key | Extra   | 
+----------------------+--------------+-----+----------------+ 
| id     | int(11)  | PRI | auto_increment | 
| first_aid_booking_id | int(11)  |  |    | 
+----------------------+--------------+-----+----------------+ 

mysql> DESCRIBE регионы;

+----------+--------------+-----+----------------+ 
| Field | Type   | Key | Extra   | 
+----------+--------------+-----+----------------+ 
| id  | int(11)  | PRI | auto_increment | 
| name  | varchar(255) |  |    | 
+----------+--------------+-----+----------------+ 

нужно выбрать следующее:

Course ID:  first_aid_courses.id 
Date:    first_aid_courses.course_date 
Region   regions.name 
Location:   first_aid_courses.location 
Bookings:   COUNT(first_aid_bookings) 
Attendees:  COUNT(first_aid_attendees) 
Spaces Remaining: COUNT(first_aid_bookings) - COUNT(first_aid_attendees) 

Это то, что я до сих пор:

SELECT `first_aid_courses`.*, 
     COUNT(`first_aid_bookings`.`id`) AS `bookings`, 
     COUNT(`first_aid_attendees`.`id`) AS `attendees` 
FROM `first_aid_courses` 
     LEFT JOIN `first_aid_bookings` 
     ON `first_aid_courses`.`id` = 
      `first_aid_bookings`.`first_aid_course_id` 
     LEFT JOIN `first_aid_attendees` 
     ON `first_aid_bookings`.`id` = 
      `first_aid_attendees`.`first_aid_booking_id` 
WHERE (`first_aid_courses`.`location` LIKE '%$search_string%' 
      OR `first_aid_courses`.`venue` LIKE '%$search_string%') 
     AND `first_aid_courses`.`deleted` = 0 
     AND (`first_aid_bookings`.`placed` > '$five_minutes_ago' 
      AND `first_aid_bookings`.`cancelled` = 0 
       OR `first_aid_bookings`.`confirmed` = 1) 
GROUP BY `first_aid_courses`.`id` 
ORDER BY `course_date` DESC 

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

+0

Как это «не работает»? –

+0

Количество заказов/посетителей неверно – Petah

ответ

2

Хорошо, Ive ответил на мой вопрос. Иногда это помогает задать вам вопрос, чтобы выяснить ответ.

SELECT `first_aid_courses`.*, 
     `regions`.`name`       AS `region_name`, 
     COUNT(DISTINCT `first_aid_bookings`.`id`) AS `bookings`, 
     COUNT(`first_aid_attendees`.`id`)   AS `attendees` 
FROM `first_aid_courses` 
     JOIN `regions` 
     ON `first_aid_courses`.`region_id` = `regions`.`id` 
     LEFT JOIN `first_aid_bookings` 
     ON `first_aid_courses`.`id` = 
      `first_aid_bookings`.`first_aid_course_id` 
     LEFT JOIN `first_aid_attendees` 
     ON `first_aid_bookings`.`id` = 
      `first_aid_attendees`.`first_aid_booking_id` 
WHERE (`first_aid_courses`.`location` LIKE '%$search_string%' 
      OR `first_aid_courses`.`venue` LIKE '%$search_string%') 
     AND `first_aid_courses`.`deleted` = 0 
     AND (`first_aid_bookings`.`cancelled` = 0 
      AND `first_aid_bookings`.`confirmed` = 1) 
GROUP BY `first_aid_courses`.`id` 
ORDER BY `course_date` ASC 
1

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

SUM(IF(`first_aid_bookings`.`id` IS NOT NULL, 1, 0)) AS `bookings`, 
COUNT(IF(`first_aid_attendees`.`id` IS NOT NULL, 1, 0)) AS `attendees` 
+0

Я не мог заставить это работать. Он возвращает то же, что и мой запрос. – Petah

1

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

Другим значительным хитом является LIKE '% nnn%'.

Можно ли что-то сделать с этим?

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

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

Вы можете использовать подзапросы, чтобы уменьшить объем запросов LIKE.

+0

Да У меня есть индексы по многим полям (включая 2 поля, используемые в операторе 'LIKE'), но я не уверен, что они находятся на правильных полях. Кроме того, оператор 'LIKE' опущен, если пользователь не вводит запрос поиска. – Petah

+0

найдите команду EXPLAIN, чтобы сам SQL-сервер анализировал запрос - он скажет вам (несколько загадочным образом), есть ли отсутствующие индексы –

Смежные вопросы