您正在使用GROUP_CONCAT
which 是一个聚合函数,但不使用 GROUP BY。MySQL 确实允许隐式分组,您可以在其中选择既不在 group by 也不在聚合中的列,但正如您所见,您可能会遇到问题。我也不推荐使用 SELECT *,所以你的查询最好写成:
SELECT p.prod_id,
p.Prod_Name,
p.prod_desc,
p.prod_nem,
p.prod_cat,
p.prod_minpric,
p.prd_minbid,
p.prod_marks,
p.prod_added, GROUP_CONCAT(img_url) urls
FROM `ci_products` p
JOIN `ci_prodimages` i
ON p.`img_pid`= i.`prod_id`
WHERE `prod_cat` = '9'
GROUP BY p.prod_id, p.Prod_Name, p.prod_desc, p.prod_nem, p.prod_cat, p.prod_minpric, p.prd_minbid, p.prod_marks, p.prod_added
在 MySQL 中(并且根据 SQL 标准),以下内容也是合法的:
SELECT p.prod_id,
p.Prod_Name,
p.prod_desc,
p.prod_nem,
p.prod_cat,
p.prod_minpric,
p.prd_minbid,
p.prod_marks,
p.prod_added, GROUP_CONCAT(img_url) urls
FROM `ci_products` p
JOIN `ci_prodimages` i
ON p.`img_pid`= i.`prod_id`
WHERE `prod_cat` = '9'
GROUP BY p.prod_id;
由于prod_id
是表的主键,ci_products
因此不必按所有列分组,因为它们在功能上依赖于主键,但是,MySQL 并未严格执行此标准,这可能导致意外行为,因此我仍然建议明确列出您分组的所有列。
下面是我之前写的一个标准解释,用于解释 MySQL 隐式分组是如何工作的,以及我为什么要避免它:
我建议尽可能避免 MySQL 提供的隐式分组,我的意思是在选择列表中包含列,即使它们不包含在聚合函数或 group by 子句中。
想象一下下面的简单表(T):
ID | Column1 | Column2 |
----|---------+----------|
1 | A | X |
2 | A | Y |
在 MySQL 中,您可以编写
SELECT ID, Column1, Column2
FROM T
GROUP BY Column1;
这实际上打破了 SQL 标准,但它在 MySQL 中有效,但问题是它是不确定的,结果:
ID | Column1 | Column2 |
----|---------+----------|
1 | A | X |
不比正确或不正确
ID | Column1 | Column2 |
----|---------+----------|
2 | A | Y |
所以你说的是给我一个不同的值Column1
,两个结果集都满足,那么你怎么知道你会得到哪一个?好吧,您不知道,这似乎是一个相当流行的误解,您可以添加和ORDER BY
子句来影响结果,例如以下查询:
SELECT ID, Column1, Column2
FROM T
GROUP BY Column1
ORDER BY ID DESC;
将确保您获得以下结果:
ID | Column1 | Column2 |
----|---------+----------|
2 | A | Y |
由于ORDER BY ID DESC
, 然而这不是真的(如此处所示)。
MySQL文档状态:
服务器可以从每个组中自由选择任何值,因此除非它们相同,否则选择的值是不确定的。此外,从每个组中选择值不会受到添加 ORDER BY 子句的影响。
因此,即使您有这样的订单,直到每组选择一行之后才适用,并且这一行是不确定的。
SQL 标准确实允许选择列表中的列不包含在 GROUP BY 或聚合函数中,但是这些列必须在功能上依赖于 GROUP BY 中的列。例如,示例表中的 ID 是 PRIMARY KEY,所以我们知道它在表中是唯一的,所以下面的查询符合 SQL 标准,在 MySQL 中运行,目前在许多 DBMS 中会失败(在编写 Postgresql 时)是我所知道的最接近正确实施标准的 DBMS):
SELECT ID, Column1, Column2
FROM T
GROUP BY ID;
由于每一行的 ID 是唯一的,因此每个 ID 只能有一个值Column1
,一个值Column2
对于每一行返回的内容没有歧义。