所以我正在为一家商店创建部分。商店可以有多个范围,如果没有为给定的 store_id
设置 section_identifier
,它应该回退到全局商店 0
.
我想要的 SQL 命令应该返回任何相关给定商店的 section_options
列表。
我的表格示例:
从 my_table 中选择*:
+----+--------------------+----------------------+----------+
| id | section_identifier | option_identifier | store_id |
+----+--------------------+----------------------+----------+
| 17 | header | header_option_one | 1 |
| 18 | footer | footer_option_one | 0 |
| 19 | homepage_feature | homepage_feature_one | 0 |
| 23 | header | header_option_three | 0 |
| 25 | homepage_feature | homepage_feature_one | 1 |
+----+--------------------+----------------------+----------+
因此 section_identifier
是唯一的,我需要为商店 1 返回的 ID 为 17、18 和 25。
当我运行时:
SELECT * FROM my_table GROUP BY section_identifier
它返回:
+----+--------------------+----------------------+----------+
| id | section_identifier | option_identifier | store_id |
+----+--------------------+----------------------+----------+
| 18 | footer | footer_option_one | 0 |
| 23 | header | header_option_three | 0 |
| 19 | homepage_feature | homepage_feature_one | 0 |
+----+--------------------+----------------------+----------+
这意味着如果我运行SELECT * FROM my_table GROUP BY section_identifier DESC
:
我得到了响应(这是我想要的输出):
+----+--------------------+----------------------+----------+
| id | section_identifier | option_identifier | store_id |
+----+--------------------+----------------------+----------+
| 25 | homepage_feature | homepage_feature_one | 1 |
| 17 | header | header_option_one | 1 |
| 18 | footer | footer_option_one | 0 |
+----+--------------------+----------------------+----------+
虽然这有效,但我不明白为什么。
据我所知,最初的GROUP BY
应该获得数据库中的第一个实例,IE我期望的响应应该是:
+----+--------------------+----------------------+----------+
| id | section_identifier | option_identifier | store_id |
+----+--------------------+----------------------+----------+
| 18 | footer | footer_option_one | 0 |
| 17 | header | header_option_three | 1 |
| 19 | homepage_feature | homepage_feature_one | 0 |
+----+--------------------+----------------------+----------+
但是,它似乎以某种方式引用了我的 store_id
?我尝试了几种不同的组合,每次都奇怪地得到我预期的结果,但我不明白为什么。
有人可以向我解释一下吗?
附注
我尝试更新 id = 7
的 option_identifier
以查看 MySql 是否引用磁盘上保存的最新内容,但结果没有改变。
另外:我不打算使用此功能或寻求替代方案,我只是想问它是怎么回事?
最佳答案
SELECT * FROM my_table GROUP BY section_identifier
是无效的 SQL
查询。
GROUP BY
如何工作?
让我们获取上面的查询并看看GROUP BY
是如何工作的。首先,数据库引擎选择与 WHERE
子句匹配的所有行。此查询中没有 WHERE
子句;这意味着表的所有行都用于生成结果集。
然后,它使用 GROUP BY
子句中指定的表达式对行进行分组:
+----+--------------------+----------------------+----------+
| id | section_identifier | option_identifier | store_id |
+----+--------------------+----------------------+----------+
| 17 | header | header_option_one | 1 |
| 23 | header | header_option_three | 0 |
+----+--------------------+----------------------+----------+
| 18 | footer | footer_option_one | 0 |
+----+--------------------+----------------------+----------+
| 19 | homepage_feature | homepage_feature_one | 0 |
| 25 | homepage_feature | homepage_feature_one | 1 |
+----+--------------------+----------------------+----------+
我在上面的列表中标记了组,以使一切变得清晰。
下一步,数据库引擎从每个组中生成一行。但如何呢?
查询的 SELECT
子句是 SELECT *
。 *
代表表格列的完整列表;在本例中,SELECT *
是一种简短的写法:
SELECT id, section_identifier, option_identifier, store_id
让我们分析第一组的 id
列的值。数据库引擎应该为 id
选择什么值? 17
还是23
?为什么是17
,为什么是23
?
它没有任何标准来支持 17
而不是 23
。它只是选择其中之一(可能是 17
但这取决于很多内部因素)并选择其中之一。
确定 section_identifier
的值没有问题。它是用于GROUP BY
的列,组中的所有值都相等。
在 option_identifier
和 store_id
列上再次出现选择困境。
根据标准SQL
,您的查询无效且无法执行。但是,某些数据库引擎按上述方式运行它。不存在的表达式的值(至少是以下之一):
- 用在
GROUP BY
子句中; - 与
GROUP BY
aggregate functions 一起使用在SELECT
子句中; - 功能上依赖于
GROUP BY
子句中使用的列;
不确定。
自版本 5.7.5
起,MySQL
实现 functional dependency detection并且默认情况下,它会拒绝像您这样的无效 GROUP BY
查询。
如何让它发挥作用
我不清楚你想如何获得结果集。无论如何,如果您想从表中获取一些行,那么GROUP BY
不是正确的方法。 GROUP BY
不从表中选择行,它使用表中的值生成新值。大多数情况下,GROUP BY
生成的行与源表中的任何行都不匹配。
您可以在 this answer 中找到问题的可能解决方案。在阅读并理解这个想法之后,您必须自己编写查询(并且您非常清楚应该如何选择“获胜”行)。
关于mysql - GROUP BY DESC 如何选择顺序?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35747846/