Jus*_*tin 5 mysql group-by sql-order-by
解决见下文
我正在尝试同时使用GROUP BY和ORDER BY在我的查询中检索按难度排序的数据。我必须使用 ,GROUP BY因为GROUP CONCAT某些表(例如“lookup_peripheral”)将多个值链接到同一个键 (content_id)。我理解为什么 MYSQL 在执行此任务时不能使用索引,因为 GROUP BY 和 ORDER BY 语句不共享相同的字段。但是,我正在寻找不需要一天即可检索结果的替代解决方案。
如果省略GROUP BYorORDER BY子句,则数据库使用索引,但结果要么缺少所有外围设备,要么未按难度排序。
我在 'lookup_difficulty' 表中FROM使用,所以我可以使用该索引对结果进行排序。这些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 |
+---------------+-----------------+------------------+
Run Code Online (Sandbox Code Playgroud)
:
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 |
+------------+---------------+
Run Code Online (Sandbox Code Playgroud)
以下不是在 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
Run Code Online (Sandbox Code Playgroud)
最终目标是使用连接的正确外围设备检索按难度排序的结果。我想我需要一个子查询来实现这一点。
编辑:回答如下:
弄清楚了。我做了我怀疑我必须做的事情,即添加子查询。由于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
Run Code Online (Sandbox Code Playgroud)
我使用了 aLEFT OUTER因为有些条目没有任何外围设备。对于大多数表的 40k 行数据库,在 400MHz 处理器上的总查询时间现在为 0.02 秒,100Hz RAM 为 128MB。
EXPLAIN现在给我USING INDEX的lookup_difficulty表。我添加了这个来实现:
ALTER TABLE `pictuts`.`lookup_difficulty` DROP PRIMARY KEY ,
ADD PRIMARY KEY ( `difficulty_id` , `content_id` )
Run Code Online (Sandbox Code Playgroud)
编辑 2 我注意到使用分页偏移较大时,页面加载速度会慢很多。您可能在其他网站上也遇到过这种情况。幸运的是,正如Peter Zaitsev所指出的那样,有一种方法可以避免这种情况。这是我更新的片段,用于实现 30K 或 0 偏移量的相同计时:
FROM
SELECT lookup_difficulty.content_id, lookup_difficulty.difficulty_id
FROM lookup_difficulty
LIMIT '.$offset.', '.$per_page.'
) ld
Run Code Online (Sandbox Code Playgroud)
现在只需添加ld.whatever到每一个JOIN制作中,你就拥有了!我的查询现在看起来一团糟,但至少它是优化的。我认为没有人会在阅读这篇文章时走到这一步......
加上贾斯汀的回答,这个问题就从未回答的列表中消失了:
弄清楚了。我做了我怀疑我必须做的事情,那就是添加一个子查询。由于 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
Run Code Online (Sandbox Code Playgroud)
我使用了 LEFT OUTER,因为有些条目没有任何外围设备。现在,对于大多数表的 40k 行数据库,在具有 128MB 100Hz RAM 的 400MHz 处理器上,总查询时间为 0.02 秒。
EXPLAIN 现在为我提供了lookup_difficulty 表的USING INDEX。我添加了这个来实现这个目的:
ALTER TABLE pictuts.lookup_difficulty DROP PRIMARY KEY ,
ADD PRIMARY KEY ( difficulty_id , content_id )
Run Code Online (Sandbox Code Playgroud)
编辑2 我注意到,使用分页进行大偏移量时,页面加载速度会相当慢。您可能在其他网站上也经历过这种情况。幸运的是,正如 Peter Zaitsev 指出的那样,有一种方法可以避免这种情况。这是我更新的代码片段,用于实现 30K 或 0 偏移量的相同计时:
FROM
SELECT ld.content_id, ld.difficulty_id
FROM lookup_difficulty ld
LIMIT '.$per_page.' OFFSET '.$offset.'
) ld
Run Code Online (Sandbox Code Playgroud)
现在只需将 ld.whatever 添加到每个 JOIN 中即可!我的查询现在看起来一团糟,但至少它得到了优化。我认为没有人能读到这里……
| 归档时间: |
|
| 查看次数: |
2670 次 |
| 最近记录: |