mysql - 快速复杂的查询来选择预订

标签 mysql optimization query-optimization

我正在尝试编写一个查询来获取类(class)信息以及预订和参加者的数量。每个类(class)可以有多个预订,每个预订可以有多个参加者。

我们已经有了一份工作报告,但它使用多个查询来获取所需的信息。一种用于获取类(class),一种用于获取预订,一种用于获取参加人数。由于数据库的大小已经增大,这非常慢。

报告有许多额外条件:

  • 预订人数必须超过 5 人 分钟前,或已确认
  • 预订不得取消
  • 不得将类(class)标记为已删除
  • 类(class)地点必须LIKE搜索字符串
  • 未预订的类(class)必须出现在结果中

这是表结构:(我省略了不需要的信息。所有字段不为空且没有默认值)

mysql> 描述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> 描述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> 描述first_aid_attendees;

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

mysql> 描述区域;

+----------+--------------+-----+----------------+
| 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 行,因此任何有关使其快速运行的帮助都会受到赞赏(例如要索引哪些字段)。

最佳答案

好的,我已经回答了我自己的问题。有时提出问题有助于您找出答案。

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  

关于mysql - 快速复杂的查询来选择预订,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4038041/

相关文章:

mysql - 使用日期范围和数字过滤器连接 2 个表

php - 使用 PHP 将 Ajax POST 数据保存到文件

java - JVM JIT 能否专门化子类中的非覆盖方法?

C++——在优化例程中追一段NaN

php - 加速 php/mysql 查询/连接的正确使用?

MySQL 统计 10 万条记录条件需要 6 秒

mysql - 使用 MySQL 进行快速交叉表更新

mysqldump导致数据库连接错误?

php - WordPress:移动多站点会导致建立数据库连接时出错

c - 从数据流 : 中选择前 k 个(百分比)项目的有效算法