0

在我正在开发的应用程序中,用户必须设置参数来定义他将获得的最终产品。

我的表如下所示:

Categories
-------------
Id   Name
1     Material
2     Color
3     Shape


Parameters
-------------
Id   CategoryId  Name
1     1           Wood
2     1           Plastic
3     1           Metal
4     2           Red
5     2           Green
6     2           Blue
7     3           Round
8     3           Square
9     3           Triangle

Combinations
-------------
Id
1
2
...

ParametersCombinations
----------------------
CombinationId  ParameterId
1               1
1               4
1               7
2               1
2               5
2               7

现在只有一些参数组合可供用户使用。在我的例子中,他可以得到一个红色圆形木制物品或一个绿色圆形木制物品,但不是蓝色的,因为我无法生产它。

假设用户选择了木材和圆形参数。我如何请求知道只有红色和绿色可用,以便我可以为他禁用蓝色选项?还是有更好的方法来为我的数据库建模?

4

2 回答 2

0

让我们假设您以以下格式提供所选参数 id

    // I call this a **parameterList** for convenience sake.
    (1,7) // this is parameter id 1 and id 7. 

我还假设您正在使用一些脚本语言来帮助您开发应用程序。像红宝石或PHP。

我还假设您希望尽可能避免将尽可能多的逻辑放入存储过程或 MySQL 查询中。

另一个假设是您使用的是Rails、Symfony 或CakePHP 等Rapid Application MVC 框架之一。

你的逻辑是:

  1. 找到包含所有参数的所有组合,parameterList并将这些找到的组合放在一个名为的列表中relevantCombinations
  2. 查找包含列表中至少 1 个组合的所有 parameters_combinations relevantCombinations。仅检索唯一的参数值。

前两个步骤可以使用简单的 Model::find 方法和我上面描述的框架中的 forloop 来解决。

如果您不使用框架,那么使用原始脚本语言也很酷。

如果您在 MySQL 查询中需要它们,这里有一些可能的查询。请注意,这些不是最佳查询所必需的。

第一个是

SELECT * FROM (
  SELECT `PossibleList`.`CombinationId`, COUNT(`PossibleList`.`CombinationId`) as number
    FROM (
      SELECT `CombinationId` FROM `ParametersCombinations` 
        WHERE `ParameterId` IN (1, 7)
    ) `PossibleList` GROUP BY `PossibleList`.`CombinationId`
) `PossibleGroupedList` WHERE `number` = 2;
-- note that the (1, 7) and the number 2 needs to be supplied by your app. 
-- 2 refers to the number of parameters supplied. 
-- In this case you supplied 1 and 7 therefore 2.

要确认,请查看http://sqlfiddle.com/#!2/16831/3

请注意我是如何故意有一个组合 3,它只有参数 1 但没有 7。因此查询没有给你返回 3,而只有 1 和 2。随意调整第一行中的星号 *。

第二个是

SELECT DISTINCT(`ParameterID`) 
FROM `ParametersCombinations`
WHERE `CombinationId` IN (1, 2);
-- note that (1, 2) is the result we expect from the first step. 
-- the one we call relevantCombinations

要确认,请查看http://sqlfiddle.com/#!2/16831/5

我不建议成为受虐狂并尝试在单个查询中获得答案。

我也不推荐使用我提供的 MySQL 查询。它不那么受虐。但对我来说足够受虐不推荐这种方式。

由于您没有指明除 mysql 之外的任何标签,我怀疑您使用 mysql 更强大。因此我的答案包含mysql。

我最强烈的建议是我的第一个。充分利用已建立的框架,把你的逻辑放在业务逻辑层。不在数据层。即使您不使用框架而只使用原始 php 和 ruby​​,这仍然是比 MySQL 更好的放置逻辑的地方。

我看到 T 在单个 MySQL 查询中给出了答案,但我可以告诉你,他只考虑 1 个参数。

请参阅此部分:

WHERE ParameterId = 7  -- 7 is the selected parameter

您可以使用 forloop 和附加 OR 子句通过一些技巧来调整他/她的答案。

同样,我不建议在构建应用程序的大局中这样做。

我还用http://sqlfiddle.com/#!2/2eda4/2测试了他/她的答案。可能有 1 或 2 个小错误。

总之,我的建议按强度降序排列:

  1. 使用 Rails 或 CakePHP 之类的框架以及伪代码步骤 1 和 2 以及find您需要的任意数量。(最强)
  2. 使用原始脚本语言和伪代码步骤 1 和 2 以及您需要的尽可能多的简单查询。
  3. 使用我创建的原始 MySQL 查询。(最弱)

PS 我在查询中省略了关于如何获取参数名称的部分。但鉴于您可以从我的回答中获得 ParameterID,我认为这很简单。我还遗漏了您可能需要如何删除已选择的参数 (1, 7)。同样,这对你来说应该是微不足道的。

于 2013-08-21T15:23:15.263 回答
0

尝试以下

SELECT p.*, pc.CombinationId
FROM Parameters p
-- get the parameter combinations for all the parameters
JOIN ParametersCombinations pc
  ON pc.ParameterId = p.Id
-- filter the parameter combinations to only combinations that include the selected parameter
JOIN (
    SELECT CombinationId
    FROM ParametersCombinations
    WHERE ParameterId = 7      -- 7 is the selected parameter
) f ON f.CombinationId = pc.CombinationId

或者删除已经选择的参数

SELECT p.*, pc.CombinationId
FROM Parameters p
JOIN ParametersCombinations pc
  ON pc.ParameterId = p.Id
JOIN (
    SELECT CombinationId
    FROM ParametersCombinations
    WHERE ParameterId IN (7, 1)
) f ON f.CombinationId = pc.CombinationId
WHERE ParameterId NOT IN (7, 1)
于 2013-08-21T14:32:07.140 回答