加入2个表 - 根据需要得到不同的结果

时间:2013-08-15 15:38:03

标签: mysql sql join

所以我又来了。我有2张桌子:

ci_products:

enter image description here

ci_prodimages:

http://img832.imageshack.us/img832/8672/kv3b.png

我有一个带有join和GROUP_CONCAT的SQL查询。

SELECT *, GROUP_CONCAT(img_url) urls FROM (`ci_products`) 
JOIN `ci_prodimages` ON `ci_prodimages`.`img_pid`=`ci_products`.`prod_id` 
WHERE `prod_cat` = '4' OR `prod_cat` = '8' OR `prod_cat` = '9' OR `prod_cat` = '10'

此SQL应返回所有3个产品。但它只返回prod_cat - 10的那个。其他一切都在运作但是这个。

此查询:

SELECT *, GROUP_CONCAT(img_url) urls FROM (`ci_products`) 
JOIN `ci_prodimages` ON `ci_prodimages`.`img_pid`=`ci_products`.`prod_id` 
WHERE `prod_cat` = '9'

结果为null结果。

任何帮助表示赞赏。感谢

2 个答案:

答案 0 :(得分:1)

您正在使用GROUP_CONCAT这是一个聚合函数,但不使用GROUP BY。 MySQL确实允许隐式分组 选择既不在组中也不在聚合中的列,但正如您所见,您可能会遇到问题。我也不建议使用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,但事实并非如此(as demonstrated here)。

MySQL documents州:

  

服务器可以自由选择每个组中的任何值,因此除非它们相同,否则所选的值是不确定的。此外,添加ORDER BY子句不会影响每个组中值的选择。

因此,即使您有一个订单,但在每个组选择了一行之后才会适用,而且这一行是不确定的。

SQL-Standard允许选择列表中的列不包含在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值,对于每行返回的内容没有歧义。

答案 1 :(得分:0)

inner join仅返回两个表中具有匹配项的行:

FROM ci_products p
JOIN ci_prodimages i ON i.img_pid = p.prod_id

尝试使用left join,它会返回左侧表格中的所有条目:

FROM ci_products p
LEFT JOIN ci_prodimages i ON i.img_pid = p.prod_id