简体   繁体   English

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

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

In the application I am developing, the user has to set parameters to define the end product he will get. 在我正在开发的应用程序中,用户必须设置参数以定义将要获得的最终产品。

My tables look like this : 我的桌子看起来像这样:

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

Now only some combinations of parameters are available to the user. 现在,只有某些参数组合可供用户使用。 In my example, he could get a red round wooden thingy or a green round wooden thingy but not a blue one because I can't produce it. 在我的示例中,他可以得到一个红色的圆木东西或一个绿色的圆木东西,但不能得到蓝色的东西,因为我无法生产它。

Let's say the user selected wood and round parameters. 假设用户选择了wood和round参数。 How do I make a request to know that there's only red and green available so I can disable the blue option for him ? 我如何请求知道只有红色和绿色可用,所以我可以为他禁用蓝色选项? Or is there some better way to model my database ? 还是有一些更好的方法来对数据库建模?

Try the following 尝试以下

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

Or removing the already selected parameters 或删除已选择的参数

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)

Let us assume you provide the selected parameters id in the following format 让我们假设您以以下格式提供选定的参数id

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

I am also assuming you are using some scripting language to help you with your app. 我还假设您正在使用某种脚本语言来帮助您使用应用程序。 Like ruby or php. 像红宝石或PHP。

I am also assuming you want to avoid putting as much logic into your stored procedure or MySQL queries as much as possible. 我还假设您想避免在存储过程或MySQL查询中尽可能多地添加逻辑。

Another assumption is that you are using one of the Rapid Application MVC Frameworks like Rails, Symfony or CakePHP. 另一个假设是您使用的是Rapid Application MVC框架之一,例如Rails,Symfony或CakePHP。

Your logic would be: 您的逻辑将是:

  1. Find all the combinations that contain ALL the parameters in your parameterList and put these found combinations in a list called relevantCombinations 在您的parameterList找到包含所有参数的所有组合,并将找到的这些组合放在一个名为relevantCombinations的列表中
  2. Find all the parameters_combinations that contain at least 1 of the combinations in the list relevantCombinations . 找到所有包含该组合中的至少1在列表中parameters_combinations relevantCombinations Retrieve only the unique parameter values. 仅检索唯一的参数值。

First two steps can be solved using simple Model::find methods and a forloop in the frameworks I described above. 可以使用简单的Model :: find方法和上述框架中的forloop来解决前两个步骤。

If you are not using frameworks, it is also cool to use the scripting language raw. 如果您不使用框架,那么使用原始脚本语言也很酷。

If you require them in MySQL queries, here are some possible queries. 如果您在MySQL查询中需要它们,这里是一些可能的查询。 Be aware that these are not necessary the best queries. 请注意,这些不是最佳查询所必需的。

First one is 第一个是

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.

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

Note how I purposely have a Combination 3 which only has the Parameter 1 but not 7. Therefore the query did not give you back 3, but only 1 and 2. Feel free to tweak the asterisk * in the first line. 请注意,我是如何故意组合3的,其中只有参数1而没有参数7。因此查询并没有给您3,而只有1和2。请随意在第一行中调整星号*。

Second one is 第二个是

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

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

I do not recommend being a masochist and attempt to get your answer in a single query. 我不建议自己成为受虐狂,并尝试在单个查询中获得答案。

I also do NOT recommend using the MySQL queries I have supplied. 我也不建议使用我提供的MySQL查询。 It is less masochistic. 它不是受虐狂。 But sufficiently masochistic for me NOT to recommend this way. 但是对于我来说,过于受虐狂就不推荐这种方式。

Since you did not indicate any tag other than mysql, I suspect that you are stronger with mysql. 由于您未指示除mysql以外的任何标签,因此我怀疑您对mysql更为满意。 Hence my answer contains mysql. 因此,我的答案包含mysql。

My strongest suggestion would be my first. 我最强烈的建议是我的第一个建议。 Make full use of established frameworks and put your logic in the business logic layer. 充分利用已建立的框架,并将您的逻辑放入业务逻辑层。 Not in the data layer. 不在数据层。 Even if you don't use frameworks and just use raw php and ruby, that is still a better place for you to place your logic in than MySQL. 即使您不使用框架,而仅使用原始的php和ruby,仍然比MySQL更适合放置逻辑。

I saw that T gave an answer in a single MySQL query but I can tell you that (s)he considers only 1 parameter. 我看到T在单个MySQL查询中给出了答案,但我可以告诉你,他只考虑1个参数。

See this part: 看到这一部分:

WHERE ParameterId = 7  -- 7 is the selected parameter

You can adapt his/her answer with some trickery using a forloop and appending OR clauses. 您可以使用forloop并附加OR子句,通过一些技巧来调整他/她的答案。

Again, I do NOT recommend that in the big picture of building an app. 同样,我不建议在构建应用程序的全局中使用。

I have also tested his/her answer with http://sqlfiddle.com/#!2/2eda4/2 . 我还通过http://sqlfiddle.com/#!2/2eda4/2测试了他/她的答案。 There may be 1 or 2 small bugs. 可能有1个或2个小错误。

In summary, my recommendations in descending order of strength: 总而言之,我的建议按强度从高到低的顺序排列:

  1. Use a framework like Rails or CakePHP and the pseudocode step 1 and 2 and as many find as you need. 使用Rails或CakePHP之类的框架以及第1步和第2步的伪代码,并根据需要find尽可能多的对象。 (STRONGEST) (最强)
  2. Use raw scripting language and the pseudocode step 1 and 2 and as many simple queries as you need. 使用原始脚本语言以及步骤1和2的伪代码以及所需的尽可能多的简单查询。
  3. Use the raw MySQL queries I created. 使用我创建的原始MySQL查询。 (LEAST STRONG) (最少)

PS I left out the part in my queries as to how to get the name of the Parameters. PS我在查询中省略了有关如何获取参数名称的部分。 But given that you can get the ParameterIDs from my answer, I think that is trivial. 但是鉴于您可以从我的答案中获取ParameterID,因此我认为这很简单。 I have also left out how you may need to remove the already selected parameters (1, 7). 我也省略了您可能需要如何删除已经选择的参数(1、7)。 Again, that should be trivial to you. 同样,这对您来说应该是微不足道的。

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

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