【问题标题】:MySQL 5.7: Order by left-joined one-to-many tablesMySQL 5.7:按左连接的一对多表排序
【发布时间】:2019-09-12 02:18:03
【问题描述】:

数据库

mysql> DESCRIBE filtercategories;
+----------+-------------+------+-----+---------+----------------+
| Field    | Type        | Null | Key | Default | Extra          |
+----------+-------------+------+-----+---------+----------------+
| id       | int(11)     | NO   | PRI | NULL    | auto_increment |
| name     | varchar(16) | NO   |     | NULL    |                |
| position | tinyint(4)  | NO   |     | NULL    |                |
+----------+-------------+------+-----+---------+----------------+
3 rows in set (0.00 sec)

mysql> DESCRIBE tags;
+---------+--------------+------+-----+---------+----------------+
| Field   | Type         | Null | Key | Default | Extra          |
+---------+--------------+------+-----+---------+----------------+
| id      | int(11)      | NO   | PRI | NULL    | auto_increment |
| slug    | varchar(64)  | NO   | UNI | NULL    |                |
| name    | varchar(128) | NO   |     | NULL    |                |
| color   | varchar(7)   | NO   |     | NULL    |                |
| visible | tinyint(1)   | NO   |     | 0       |                |
+---------+--------------+------+-----+---------+----------------+
5 rows in set (0.00 sec)

mysql> DESCRIBE filtercategories_tags;
+-------------------+------------+------+-----+---------+----------------+
| Field             | Type       | Null | Key | Default | Extra          |
+-------------------+------------+------+-----+---------+----------------+
| id                | int(11)    | NO   | PRI | NULL    | auto_increment |
| filtercategory_id | int(11)    | NO   | MUL | NULL    |                |
| tag_id            | int(11)    | NO   | MUL | NULL    |                |
| position          | tinyint(4) | NO   |     | NULL    |                |
+-------------------+------------+------+-----+---------+----------------+
4 rows in set (0.00 sec)

目标

要返回由 position 排序的 filtercategories 列表,左连接标签也应按 position 排序。


到目前为止,我正在尝试这样的事情:

SELECT
  fc.*,
  GROUP_CONCAT(t.name) AS tagNames
FROM filtercategories fc
LEFT JOIN (filtercategories_tags fc_t, tags t)
ON (
  fc_t.filtercategory_id = fc.id AND
  t.id = fc_t.tag_id
)
GROUP BY fc.id
ORDER BY fc.position

问题是MySQL不允许使用ORDER BY fc_t.position

ER_WRONG_FIELD_WITH_GROUP:ORDER BY 子句的表达式#1 不在 GROUP BY 子句中,并且包含在功能上不依赖于 GROUP BY 子句中的列的非聚合列“foo_db.fc_t.position”;这与 sql_mode=only_full_group_by 不兼容

【问题讨论】:

  • MySQL 抱怨是有充分理由的。 fc_t.position 每组可以有多个值。你没有说你想用哪一个来做 ORDER BY。
  • 该错误消息似乎与查询不匹配。错误消息显示fc_t.position,但查询显示fc.position
  • 使用正确的GROUP BYSELECT *GROUP BY 是个大号。
  • 没有其他 dbms 将运行您的代码。

标签: mysql sql


【解决方案1】:

左连接标签也应该按位置排序。

那么你应该在GROUP_CONCAT() 中使用ORDER BY 子句:

SELECT
  fc.*,
  GROUP_CONCAT(t.name ORDER BY fc_t.position) AS tagNames
FROM filtercategories fc
LEFT JOIN filtercategories_tags fc_t ON fc_t.filtercategory_id = fc.id
LEFT JOIN tags t ON t.id = fc_t.tag_id
GROUP BY fc.id
ORDER BY fc.position

我还修复了您的 JOIN 语法。请不要在一个查询中将显式 JOIN 与逗号连接混合。这很难理解和调试。

【讨论】:

  • ORDER BY INSIDE GROUP CONCAT 是关键。顺便说一句,逗号连接是 Oracle 的 MySQL 文档的一部分:dev.mysql.com/doc/refman/5.7/en/join.html
  • @Oleg 这是一个显示不同但等效语法的示例。这并不意味着你应该使用它。我不会使用这两个查询。但这取决于你。
猜你喜欢
  • 2021-07-02
  • 2012-05-15
  • 2013-05-16
  • 1970-01-01
  • 1970-01-01
  • 2016-07-19
  • 1970-01-01
  • 2010-11-25
  • 2015-03-13
相关资源
最近更新 更多