繁体   English   中英

如何在MySQL中请求包含某些项目的列表

[英]How to request lists that contain certain items in MySQL

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

我的桌子看起来像这样:

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

现在,只有某些参数组合可供用户使用。 在我的示例中,他可以得到一个红色的圆木东西或一个绿色的圆木东西,但不能得到蓝色的东西,因为我无法生产它。

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

尝试以下

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)

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

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

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

我还假设您想避免在存储过程或MySQL查询中尽可能多地添加逻辑。

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

您的逻辑将是:

  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)。 同样,这对您来说应该是微不足道的。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM