2012-09-10 72 views
1

我有一个选择查询来建立,我不能得到它的工作propery。我希望从更先进的MySQL开发人员那里得到一些建议。 所以我的表是:Mysql select查询组concat

CREATE TABLE IF NOT EXISTS `gv` ( 
`id` int(11) NOT NULL AUTO_INCREMENT, 
`option_id` int(11) NOT NULL, 
`group_id` int(11) NOT NULL, 
PRIMARY KEY (`id`) 
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=7 ; 

INSERT INTO `gv` (`id`, `option_id`, `group_id`) VALUES 
(1, 1, 1), 
(2, 2, 2), 
(3, 3, 2), 
(4, 4, 3), 
(5, 5, 4), 
(6, 6, 4); 

CREATE TABLE IF NOT EXISTS `igv` (
`id` int(11) NOT NULL AUTO_INCREMENT, 
`item_id` int(11) NOT NULL, 
`gv_id` int(11) NOT NULL, 
PRIMARY KEY (`id`) 
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=9 ; 

INSERT INTO `igv` (`id`, `item_id`, `gv_id`) VALUES 
(1, 1, 1), 
(2, 1, 3), 
(3, 2, 1), 
(4, 2, 2), 
(6, 3, 5), 
(7, 4, 2), 
(8, 2, 6); 

CREATE TABLE IF NOT EXISTS `items` (
    `item_id` int(11) NOT NULL AUTO_INCREMENT, 
    PRIMARY KEY (`item_id`) 
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=6 ; 

INSERT INTO `items` (`item_id`) VALUES 
(1), 
(2), 
(3), 
(4), 
(5); 

现在我会解释这些表都在做:

  1. GV来自group_values。一个组就像一个物品。例如:颜色。

    • 每行都保存一个组的值。例如:组颜色(group_id)的红色(option_id)。
  2. igv来自项目组值。项目是我项目中的主要实体,就像产品一样。

    • 每行都包含项目和组值之间的关系。例如:红色的物品。
    • 它通过gv_id(igv.gv_id = gv.id)链接到gv表。
  3. 项目来自项目:)我简化了这个例子只有一列,item_id。

我需要查询:

嗯,在我的应用我有一个选择的项目(my_item)(0或多个组值附后)。 我需要定义完全相同的group_values的所有项目,或者没有为my_item组指定值。在PHP中,我可以提取所有附加的组作为一个数组与id,也是所有group_values。但是我没有办法从这个数据库中选择我需要的东西。 我非常感谢提供给这个海量时间选择的任何输入。

谢谢!

一个简短的草绘示例。在左侧,我们有与所有正确项目匹配的项目(用逗号分隔)。 enter image description here

+0

你能给一个工作的例子吗? – Neil

+0

'SELECT i.item_id,igv.id,gv.option_id,gv.group_id FROM items AS i LEFT JOIN igv ON i.item_id = igv.item_id LEFT JOIN gv ON igv.gv_id = gv.id AND gv.group_id IN(1,2) WHERE IF(gv.group_id IS NOT NULL,gv.option_id IN(1,2),1) GROUP BY i.item_id' 但为此,我需要先处理所有提供的项目,提取附加的组和它们的值。这也没有完全测试到我的应用程序,只有在这个测试的例子。 –

+0

对不起,但这并没有真正帮助我。我重读了你的问题,我假设你想将第2项与第4项匹配,因为它们对于2的group_id都有option_id 2,并且你不想将第2项与第3项匹配,因为它们具有不同的option_id group_id是4,但我不能告诉你是否想将项目2与项目1或项目5或两者匹配。 – Neil

回答

2

OK,所以下手,我们需要找到一个组中的所有项目匹配的另一个项目:

SELECT igv.item_id, sigv.item_id FROM igv 
    INNER JOIN gv ON igv.gv_id = gv.id 
    INNER JOIN gv sgv ON gv.group_id = sgv.group_id 
    INNER JOIN igv sigv ON sigv.gv_id = sgv.id 
    WHERE igv.item_id = items.item_id 
    AND sigv.item_id = similar.item_id 

然后,我们是时候只关心该选项的比赛:

SELECT igv.item_id, sigv.item_id dissimilar FROM igv 
    INNER JOIN gv ON igv.gv_id = gv.id 
    INNER JOIN gv sgv ON gv.group_id = sgv.group_id 
    INNER JOIN igv sigv ON sigv.gv_id = sgv.id 
    WHERE igv.item_id = items.item_id 
    AND sigv.item_id = similar.item_id 
    AND gv.option_id != sgv.option_id 

然后我们只对上面选择的而不是的项目感兴趣。这可以使用NOT EXISTSLEFT JOIN来完成。以下是如何与NOT EXISTS做到这一点:

SELECT items.item_id, similar.item_id similar_id 
    FROM items similar 
    INNER JOIN items 
    WHERE items.item_id != similar.item_id 
    AND NOT EXISTS (
    SELECT igv.item_id, sigv.item_id dissimilar FROM igv 
     INNER JOIN gv ON igv.gv_id = gv.id 
     INNER JOIN gv sgv ON gv.group_id = sgv.group_id 
     INNER JOIN igv sigv ON sigv.gv_id = sgv.id 
     WHERE sigv.item_id = similar.item_id 
     AND igv.item_id = items.item_id 
     AND gv.option_id != sgv.option_id 
    ) 

结果:

ITEM_ID SIMILAR_ID 
1  3 
1  5 
2  4 
2  5 
3  1 
3  4 
3  5 
4  2 
4  3 
4  5 
5  1 
5  2 
5  3 
5  4 
+0

非常感谢Neil,这解决了我的问题。 但似乎我的问题正在延伸到一个新的未考虑的级别,我忘了提及,但我也可以有多个选项附加到一个项目的同一组。但是我的错,我没有记录在第一次。无论如何...非常好的答案,我非常感谢! –

+0

嗯,在这种情况下,如果所有匹配的组都有匹配的选项,那么编写一个查询可以识别出一个项目,尽管在你的例子中,我认为我只能使它匹配项目2和4。 – Neil

1

更新:

根据您的评论,的逻辑,如果我正确了解它,你的测试数据,下表列出了导致你想为哪个ITEM_ID您提供查询。

id_provided | result 
-------------------- 
1    2 & 5 
2    1 & 4 & 5 
3    5 
4    2 & 5 
5    - 

如果这是正确的,下面的查询给出了预期的结果:

SELECT 
COALESCE(i2.item_id, i.item_id) 
FROM 
items i 
LEFT JOIN igv ON igv.item_id = i.item_id 
LEFT JOIN gv ON igv.gv_id = gv.id 
LEFT JOIN gv gv2 ON gv.group_id = gv2.group_id AND gv.option_id = gv2.option_id 
LEFT JOIN igv igv2 ON gv2.id = igv2.gv_id 
LEFT JOIN items i2 ON igv2.item_id = i2.item_id 
WHERE i.item_id = $yourItemId 
AND i2.item_id != i.item_id OR i2.item_id IS NULL 



我不知道如果我明白你想要什么,我m不知道下面的查询是否得到你想要的,因为你没有说预期的输出是什么,你的测试数据是不够的。总之,这里是我的镜头:

SELECT DISTINCT 
i.item_id 
FROM 
items i 
LEFT JOIN igv ON igv.item_id = i.item_id 
LEFT JOIN gv ON igv.gv_id = gv.id 
GROUP BY i.item_id 
HAVING 
GROUP_CONCAT(CONCAT(COALESCE(gv.option_id, 0), COALESCE(gv.group_id, 0)) ORDER BY gv.option_id, gv.group_id SEPARATOR ':') 
= 
(
SELECT 
GROUP_CONCAT(CONCAT(COALESCE(sq_gv.option_id, 0), COALESCE(sq_gv.group_id, 0)) ORDER BY sq_gv.option_id, sq_gv.group_id SEPARATOR ':') 
FROM 
items sq_i 
LEFT JOIN igv sq_igv ON sq_igv.item_id = sq_i.item_id 
LEFT JOIN gv sq_gv ON sq_igv.gv_id = sq_gv.id 
WHERE sq_i.item_id = $yourItemId /*insert the item_id here*/ 
GROUP BY sq_i.item_id 
) 

+0

感谢您的意见。在我的测试示例中,如果我用1到5中的任何项目ID替换$ yourItemId,它只输出提供的$ yourItemId。 所以我需要提供一个项目的ID和查询来选择所有其余项目女巫: - 如果有相同的组附加,那么该项目也必须具有相同的选项。 - 所提供项目的所有组均未附加到此项目。 所以如果我提供的项目有红色,那么选择的项目必须有: - 如果颜色组通过在igv上有一行连接,则为红色 - 如果没有附加颜色组,则为任何颜色 –

+0

@ SerbuFlorin-Adrian更新了我的答案。 – fancyPants

+0

我非常感谢你的兴趣,现在我想现在我解释了理想的结果,因为其他人可以正确理解它。所以请检查我更新的问题 - 附图。 –