已解决 见下文
我正在尝试同时使用 GROUP BY
和 ORDER BY
在我检索按难度排序的数据的查询中。我必须使用 GROUP BY
因为GROUP CONCAT
由于某些表(例如“lookup_peripheral”)将多个值链接到同一个键 (content_id)。我理解为什么 MYSQL 在执行此任务时不能使用索引,因为 GROUP BY 和 ORDER BY 语句不共享相同的字段。但是,我正在寻找不需要一天即可检索结果的替代解决方案。
如果我省略 GROUP BY
或 ORDER BY
子句,则数据库使用索引,但结果要么缺少所有外围设备,要么未按难度排序。
我在 FROM
中使用了“lookup_difficulty”表所以我可以使用该索引对结果进行排序。 lookup_xxxxx
表存储每个允许的值,然后是其他表,例如 peripheral
通过 content_id 将提交链接到值。一切引用提交content_id
. content
表包含基本信息,例如成员 ID、姓名等。
如果我的帖子不够清楚,我深表歉意。
mysql> describe peripheral;
+------------------+----------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+------------------+----------+------+-----+---------+-------+
| peripheral_id | int(2) | NO | PRI | NULL | |
| peripheral | char(30) | NO | | NULL | |
| peripheral_total | int(5) | NO | | NULL | |
+------------------+----------+------+-----+---------+-------+
mysql> select * from peripheral;
+---------------+-----------------+------------------+
| peripheral_id | peripheral | peripheral_total |
+---------------+-----------------+------------------+
| 1 | periph 1 | 0 |
| 2 | periph 2 | 1 |
| 3 | periph 3 | 3 |
+---------------+-----------------+------------------+
:
mysql> describe lookup_peripheral;
+---------------+---------+------+------+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+---------------+---------+------+------+---------+-------+
| content_id | int(10) | NO | INDEX| NULL | |
| peripheral_id | int(2) | NO | | NULL | |
+---------------+---------+------+------+---------+-------+
mysql> mysql> select * from lookup_peripheral;
+------------+---------------+
| content_id | peripheral_id |
+------------+---------------+
| 74 | 2 |
| 74 | 5 |
| 75 | 2 |
| 75 | 5 |
| 76 | 3 |
| 76 | 4 |
+------------+---------------+
以下不是在 lookup_difficulty 上使用索引,而是使用表排序和临时表。
SELECT group_concat(DISTINCT peripheral.peripheral) as peripheral, content.member, .....
FROM (lookup_difficulty)
LEFT OUTER JOIN lookup_peripheral ON lookup_difficulty.content_id = lookup_peripheral.content_id
LEFT OUTER JOIN peripheral ON peripheral.peripheral_id = lookup_peripheral.peripheral_id
.....
LEFT OUTER JOIN programmer ON programmer.programmer_id = lookup_programmer.programmer_id
LEFT OUTER JOIN lookup_programming_language ON lookup_difficulty.content_id = lookup_programming_language.content_id
GROUP BY lookup_difficulty.content_id
ORDER BY lookup_dfficulty.difficulty_id
LIMIT 30
最终目标是使用连接的正确外围设备检索按难度排序的结果。我想我需要一个子查询来实现这一点。
编辑:下面的答案:
弄清楚了。我做了我怀疑我必须做的事情,即添加子查询。由于MYSQL每个表只能使用一个索引,我无法
GROUP BY
和 SORT BY
一起用于我的特定设置。相反,我添加了另一个查询,该查询将使用不同表上的另一个索引将外围设备组合在一起。这是我在 SELECT
中添加的内容上面的声明:(SELECT group_concat(DISTINCT peripheral.peripheral) as peripheral
FROM lookup_peripheral
LEFT OUTER JOIN peripheral ON peripheral.peripheral_id = lookup_peripheral.peripheral_id
WHERE lookup_difficulty.content_id = lookup_peripheral.content_id
GROUP BY lookup_peripheral.content_id
LIMIT 1) as peripheral
我用了
LEFT OUTER
因为有些条目没有任何外围设备。对于大多数表的 40k 行数据库,在 400MHz 处理器上的总查询时间现在为 0.02 秒,128MB 100Hz RAM。EXPLAIN
现在给我一个 USING INDEX
为 lookup_difficulty
table 。我添加了这个来实现:ALTER TABLE `pictuts`.`lookup_difficulty` DROP PRIMARY KEY ,
ADD PRIMARY KEY ( `difficulty_id` , `content_id` )
编辑 2
我注意到使用分页的偏移量较大时,页面加载速度会慢很多。您可能在其他网站上也遇到过这种情况。幸运的是,正如 Peter Zaitsev 所指出的,有一种方法可以避免这种情况。 .这是我更新的片段,用于实现 30K 或 0 偏移量的相同计时:
FROM
SELECT lookup_difficulty.content_id, lookup_difficulty.difficulty_id
FROM lookup_difficulty
LIMIT '.$offset.', '.$per_page.'
) ld
现在只需添加
ld.whatever
到每个 JOIN
制作完成,您就拥有了!我的查询现在看起来一团糟,但至少它是优化的。我认为没有人会在阅读这篇文章时走到这一步......
最佳答案
输入 Justin 的答案,这样这个问题就会从未回答的列表中消失:
弄清楚了。我做了我怀疑我必须做的事情,即添加子查询。由于 MYSQL 每个表只能使用一个索引,因此我无法针对我的特定设置将 GROUP BY 和 SORT BY 组合在一起。相反,我添加了另一个查询,该查询将使用不同表上的另一个索引将外围设备组合在一起。这是我在上面的 SELECT 语句中添加的内容:
(SELECT group_concat(DISTINCT p.peripheral) as peripheral
FROM lookup_peripheral lp
LEFT JOIN peripheral p ON p.peripheral_id = lp.peripheral_id
WHERE ld.content_id = lp.content_id
GROUP BY lp.content_id
LIMIT 1) as peripheral
我使用了 LEFT OUTER,因为有些条目没有任何外围设备。对于大多数表的 40k 行数据库,在 400MHz 处理器上的总查询时间现在为 0.02 秒,100Hz RAM 为 128MB。
EXPLAIN 现在给了我一个用于 lookup_difficulty 表的 USING INDEX。我添加了这个来实现:
ALTER TABLE pictuts.lookup_difficulty DROP PRIMARY KEY ,
ADD PRIMARY KEY ( difficulty_id , content_id )
编辑 2 我注意到使用分页偏移较大时,页面加载速度会慢很多。您可能在其他网站上也遇到过这种情况。幸运的是,正如 Peter Zaitsev 所指出的那样,有一种方法可以避免这种情况。这是我更新的片段,用于实现 30K 或 0 偏移量的相同计时:
FROM
SELECT ld.content_id, ld.difficulty_id
FROM lookup_difficulty ld
LIMIT '.$per_page.' OFFSET '.$offset.'
) ld
现在只需将 ld.whatever 添加到每个 JOIN 中,就可以了!我的查询现在看起来一团糟,但至少它是优化的。我认为没有人会在阅读这篇文章时走到这一步......
关于mysql - 使用 GROUP BY、ORDER BY 和 GROUP_CONCAT 进行索引,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7381828/