Mysql 快速复杂查询以选择预订
我正在尝试编写一个查询,以获取课程信息以及预订和与会者的数量。每门课程可以有多个预订,并且每个预订可以有多个参与者 我们已经有了一个工作报告,但它使用多个查询来获取所需的信息。一个用于获取课程,一个用于获取预订,另一个用于获取出席人数。这是非常缓慢的,因为数据库的大小已经增长到 报告有许多附加条件:Mysql 快速复杂查询以选择预订,mysql,optimization,query-optimization,Mysql,Optimization,Query Optimization,我正在尝试编写一个查询,以获取课程信息以及预订和与会者的数量。每门课程可以有多个预订,并且每个预订可以有多个参与者 我们已经有了一个工作报告,但它使用多个查询来获取所需的信息。一个用于获取课程,一个用于获取预订,另一个用于获取出席人数。这是非常缓慢的,因为数据库的大小已经增长到 报告有许多附加条件: 预订次数必须超过5次 几分钟前,还是已经确认了 预订不能取消 不得将课程标记为已删除 课程地点和地点必须像搜索字符串一样 结果中必须显示未预订的课程 这是表结构:(我省略了不需要的信息。所有字段
- 预订次数必须超过5次 几分钟前,还是已经确认了
- 预订不能取消
- 不得将课程标记为已删除
- 课程地点和地点必须像搜索字符串一样
- 结果中必须显示未预订的课程
+------------------+--------------+-----+----------------+
| 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>描述急救预约
+-----------------------+--------------+-----+----------------+
| 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>描述急救参与者
+----------------------+--------------+-----+----------------+
| 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行,因此任何帮助都将非常感谢(如索引哪些字段) 这完全未经测试,但可以尝试为预订和与会者选择非空行计数,如下所示:
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`
除非您有它,但只是不显示它,否则请仔细查看索引,如果没有它们,则会在任何引用主键以外的任何查询上损失一个数量级的性能 另一个主要的性能影响是“%nnn%” 有可能用这些做点什么吗 但是有了一些好的索引,如果您有硬件来备份的话,这个查询应该很好 我在有数百万行的表上有类似的查询。如果查询的其余部分可以消除任何不必要的匹配,这就不是问题
您可以使用子查询来缩小类似查询的范围 好的,我回答了我自己的问题。有时候,问一个问题来找出答案会有帮助
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
怎么会“不太有效”?预订/与会者的数量是错误的。是的,我在很多字段上都有索引(包括
LIKE
语句中使用的两个字段),但我不能100%确定它们在正确的字段上。此外,除非用户在搜索查询中键入内容,否则将省略LIKE
语句。请查找EXPLAIN命令,让sql引擎本身分析查询——它将告诉您(以某种隐晦的方式)是否有任何缺少的索引,我无法使其工作。它返回与my查询相同的结果。