【问题标题】:Mysql select query group concatMysql选择查询组concat
【发布时间】:2012-09-10 10:43:33
【问题描述】:

我有一个选择查询要构建,但无法正常工作。我希望从更高级的 MySQL 开发人员那里得到一些建议。 所以我的表是:

 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. items 来自 items :) 我已将此示例简化为只有一列 item_id。

我需要查询的内容:

好吧,在我的应用程序中,我有一个选定的项目 (my_item)(附加了 0 个或多个组值)。 我需要定义了完全相同的 group_values 的所有项目,或者没有为 my_item 组指定值。在 php 中,我可以将所有附加的组提取为带有 id 的数组,也可以提取所有 group_values。但是我没有办法从这个数据库中选择我需要的东西。 我将非常感谢为这个大量耗时的选择提供的任何输入。

谢谢!

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

【问题讨论】:

  • 你能举个例子吗?
  • 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 但为此我需要首先处理所有提供的项目并提取附加的组及其值。此外,这还没有完全测试到我的应用程序中,仅在这个测试示例中。
  • 对不起,但这对我没有帮助。我重读了你的问题,我假设你想将第 2 项与第 4 项匹配,因为它们的 group_id 为 2 的 option_id 均为 2,并且你不想将第 2 项与第 3 项匹配,因为它们有不同的 option_id group_id 为 4,但我不知道您是否要将项目 2 与项目 1 或项目 5 或两者匹配。
  • 我不想将第 2 项与第 1 项匹配,因为我们的情况与第 3 项相同,它们对第 2 组有不同的选项。此外,如果没有为任何 CURRENT_ITEM 组附加选项然后它匹配。所以项目 5 将与任何其他项目匹配。我将发布一个简短的草图。
  • 这对我来说完全没有意义。当您搜索 item_id 1 时,为什么 item_id 3 匹配? option_id 和 group_id,5 和 4,不被其他项目使用。恐怕我根本不明白你在追求什么。

标签: mysql group-by group-concat mysql-select-db


【解决方案1】:

好的,所以首先我们需要找到与另一个项目匹配的组的所有项目:

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

【讨论】:

  • 非常感谢尼尔,这解决了我的问题。但似乎我的问题正在扩展到一个新的不受欢迎的水平,我忘了提及,但我也可以将多个选项附加到同一个项目的同一组。但是我没有第一次记录它是我的错。无论如何...非常好的答案,我非常感谢!
  • 啊,那么在这种情况下,如果所有匹配组都有匹配选项,则可能会编写一个将项目标识为相似的查询,尽管对于您的示例,我认为我只能让它匹配项目 2 和 4。
【解决方案2】:

更新:

根据您评论中的逻辑,如果我理解正确,以及您的测试数据,下表显示了您为查询提供的 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



我不确定我是否理解您想要什么,并且我不确定以下查询是否得到您想要的,因为您没有说明预期的输出是什么并且您的测试数据不足。无论如何,这是我的镜头:

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
)

【讨论】:

  • 感谢您的意见。在我的测试示例中,如果我将 $yourItemId 替换为从 1 到 5 的任何项目 ID,它只会输出提供的 $yourItemId。所以我需要为它提供一个项目的 id,以及选择所有其余项目的查询: - 如果附加了相同的组,那么该项目也必须具有相同的选项。 - 所提供项目中的任何组均未附加到该项目。因此,如果我提供的项目具有红色,那么所选项目必须具有: - 如果通过在 igv 上添加一行来附加颜色组,则为红色 - 如果没有附加颜色组,则为任何颜色
  • @SerbuFlorin-Adrian 更新了我的答案。
  • 非常感谢您的兴趣,现在我想我现在解释了预期的结果,因为其他人可以正确理解它。所以请检查我更新的问题 - 所附图片。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-12-24
  • 2011-05-29
  • 1970-01-01
  • 2021-05-21
  • 1970-01-01
  • 2011-09-18
  • 1970-01-01
相关资源
最近更新 更多