1

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

谢谢

编辑:

表 ci_products

在此处输入图像描述

表 ci_marks(所有可能的带有符号和描述的标记) 在此处输入图像描述

现在我的查询如下所示:

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`

查询结果: 在此处输入图像描述

然后我在 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 相关的表来建立 MN 关系吗?然后我想查询以获取所有带有相关标记的产品。当我使用 JOIN 时,它会为每个图像和标记生成多个产品,因此我使用了 group_concat。那么我会为 mark_mark 和 mark_desc 使用另一个 group_concat 吗?

编辑:

具有多个结果问题的关系表的新 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` 
4

1 回答 1

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')

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

SQL Fiddle 示例

注意

我也替换了这个:

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')
于 2013-08-16T09:02:15.017 回答