group_concat与另一个查询

时间:2013-08-16 07:34:38

标签: sql join group-concat

我想问一下,对我的应用程序有什么更好的解决方案。我有1个表:标记 - 我存储标记的位置 - 名称,符号和描述。然后我有另一张表:产品 - 每个产品都有一些标记1 - N.现在我在表产品中存储产品标记 - 列prod_marks - 以逗号分隔。然后我用另一个查询得到那些标记。我从products表中获取了所有标记的ID,然后运行查询来获取它们。它是好的还是1用join和group_concat查询另一个表让我们说:prodmarks(pmark_id,pmark_prodID,pmark_markID)会更好吗?

由于

编辑:

table ci_products

enter image description here

table ci_marks(带符号和描述的所有可能标记) enter image description here

现在我的查询如下:

SELECT `prod_id`, `prod_name`, `prod_desc`, `prod_num`, `prod_marks`, `prod_minprice`, `prod_minbid`, `prod_cat`, GROUP_CONCAT(img_url) images
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'
GROUP BY `prod_id`

查询结果: enter image description here

然后我在prod_marks中得到这样的东西:2,5,6 然后使用这些ID我运行另一个查询以获得标记'名称和描述。

第二个想法是另一个连接到新表:ci_prodmarks - 我会有pmark_id,pmark_pid(fk到prod_id),pmark_mid(fk到mark_id)以及标记符号和标记描述上的另一个group_concat

修改

这就是我现在所得到的。使用这些数据,我运行另一个查询来获取这些标记。问题是:我是否应该将另一个表格与ci_products和ci_marks相关联以形成M-N关系?此外,我想要查询以获取与其相关的标记的所有产品。当我使用JOIN时,它会为每个图像和标记产生多个产品,所以我使用了group_concat。那么我会使用另一个group_concat作为mark_mark和mark_desc吗?

修改

带有多个结果问题的关系表的新SQL

    SELECT  `prod_id` ,  `prod_name` ,  `prod_desc` ,  `prod_num` ,  `prod_marks` ,  `prod_minprice` ,  `prod_minbid` ,  `prod_cat` , GROUP_CONCAT( img_url ) images, GROUP_CONCAT( mark_mark ) marks, GROUP_CONCAT( mark_desc
SEPARATOR  ";" ) mark_descriptions
FROM (
`ci_products` ,  `ci_marks`
)
JOIN  `ci_prodimages` ON  `ci_prodimages`.`img_pid` =  `ci_products`.`prod_id` 
JOIN  `ci_prodmarks` ON  `ci_prodmarks`.`pmark_pid` =  `ci_products`.`prod_id` 
AND ci_prodmarks.pmark_mid = ci_marks.mark_id
WHERE  `prod_cat` =  '4'
OR  `prod_cat` =  '8'
OR  `prod_cat` =  '9'
OR  `prod_cat` =  '10'
GROUP BY  `prod_id` ,  `mark_id` 

1 个答案:

答案 0 :(得分:1)

您的一个问题是您按mark_id分组,这意味着每个产品最终会有多行,而不是每行中的所有标记,但这只是隐藏了另一个问题。因为您有多个一对多关系,所以您在加入时会获得笛卡尔积。想象一下prod_id = 1

的以下简单示例

图片

pid     url
--------------
1       some_url
1       some_other_url

<强>标记

pid     mark
-------------------
1       1
1       2

当您在产品ID上加入这两个时,您最终会

pid     url             mark
------------------------------
1       some_url        1
1       some_url        2
1       some_other_url  1
1       some_other_url  2

所以你得到了两者的所有组合,所以当你对这些组合进行GROUP_CONCAT时,你会得到重复的。

您需要使用子查询来执行组仲裁:

SELECT  p.prod_id,  
        p.prod_name,  
        p.prod_desc,  
        p.prod_num,  
        p.prod_marks,  
        p.prod_minprice, 
        p.prod_minbid, 
        p.prod_cat, 
        img.images, 
        m.marks,
        m.mark_descriptions
FROM    ci_products p
        INNER JOIN 
        (   SELECT  i.img_pid, GROUP_CONCAT( i.img_url ) images
            FROM    ci_prodimages i
            GROUP BY i.img_pid
        ) img
            ON img.img_pid = p.prod_id 
        INNER JOIN 
        (   SELECT  ci_prodmarks.pmark_pid, 
                    GROUP_CONCAT( ci_marks.mark_mark ) marks, 
                    GROUP_CONCAT( ci_marks.mark_desc SEPARATOR  ";" ) mark_descriptions
            FROM    ci_prodmarks 
                    INNER JOIN ci_marks
                        ON ci_prodmarks.pmark_mid = ci_marks.mark_id
            GROUP BY ci_prodmarks.pmark_pid
        ) m
            ON m.pmark_pid = p.prod_id 
WHERE   p.prod_cat IN ('4', '8', '9', '10')

<强> Example on SQL Fiddle

或者在GROUP_CONCAT中使用DISTINCT:

SELECT  p.prod_id,  
        p.prod_name,  
        p.prod_desc,  
        p.prod_num,  
        p.prod_marks,  
        p.prod_minprice, 
        p.prod_minbid, 
        p.prod_cat, 
        GROUP_CONCAT( i.img_url ) images, 
        GROUP_CONCAT( DISTINCT m.mark_mark ) marks, 
        GROUP_CONCAT( DISTINCT m.mark_desc SEPARATOR  ";" ) mark_descriptions
FROM    ci_products p
        INNER JOIN ci_prodimages i
            ON i.img_pid = p.prod_id 
        INNER JOIN ci_prodmarks pm
            ON pm.pmark_pid = p.prod_id 
        INNER JOIN ci_marks m
            ON pm.pmark_mid = m.mark_id
WHERE   p.prod_cat IN ('4', '8', '9', '10')
GROUP BY p.prod_id, p.prod_name, p.prod_desc, p.prod_num, p.prod_marks, p.prod_minprice, p.prod_minbid, p.prod_cat

<强> Example on SQL Fiddle

N.B。

我也取而代之:

WHERE `prod_cat` =  '4'
OR `prod_cat` =  '8'
OR `prod_cat` =  '9'
OR `prod_cat` =  '10'

使用单个IN语句:

WHERE   p.prod_cat IN ('4', '8', '9', '10')