Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/82.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 在一对多系统中存储和计算关系_Sql_Algorithm_Logic_One To Many - Fatal编程技术网

Sql 在一对多系统中存储和计算关系

Sql 在一对多系统中存储和计算关系,sql,algorithm,logic,one-to-many,Sql,Algorithm,Logic,One To Many,我在挠头,寻找一个合理的方法来实现这一点。标题真的很难弄清楚,所以如果你进入这篇文章是希望得到其他东西,我很抱歉。这既是一个数据库问题,也是一个逻辑问题 我在“收藏”中有100个条目。让我们把每一个都称为对象。每个对象都引用数据库中的一个条目,并有一些名称(比如obj1、obj2…)。其中一些对象是其他对象的“复合物”。因此,例如,如果obj1和obj2是输入,则obj11是输出(obj1,obj2->obj11)。甚至可能是同一对象的多个输入:obj1 x 4、obj2、obj11->obj2

我在挠头,寻找一个合理的方法来实现这一点。标题真的很难弄清楚,所以如果你进入这篇文章是希望得到其他东西,我很抱歉。这既是一个数据库问题,也是一个逻辑问题

我在“收藏”中有100个条目。让我们把每一个都称为对象。每个对象都引用数据库中的一个条目,并有一些名称(比如obj1、obj2…)。其中一些对象是其他对象的“复合物”。因此,例如,如果obj1和obj2是输入,则obj11是输出(obj1,obj2->obj11)。甚至可能是同一对象的多个输入:obj1 x 4、obj2、obj11->obj21

我正在寻找一种在改变输入的同时不断计算结果对象的方法,因此这些关系必须以某种巧妙的方式存储在数据库中,这样的计算才能以一种相当优雅的方式完成

当然,我想到了多对一表,但是在没有解析整个表的情况下,找不到一种逻辑方法来查找给定输入的结果


有人对此有什么想法吗?

你似乎在构建一种食谱系统。某些对象是由不同数量的其他对象创建的。在数据结构方面,您可以有

struct东西{
向量部分;
//…这里还有其他属性
};
结构成分{
事物成分;
整数计数;
};
这可以使用

   CREATE TABLE `Things` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
       # ... other attributes here
      PRIMARY KEY `id`
   );

   CREATE TABLE `Ingredients` (
      `id` int(11) NOT NULL AUTO_INCREMENT,           
      `result_id` int(11) NOT NULL,
      `component_id` int(11) NOT NULL, 
      `count` int(11) NOT NULL,
       PRIMARY KEY `id`
   );

   ALTER TABLE `Ingredients` FOREIGN KEY (`result_id`) REFERENCES `Thing` (`id`);
   ALTER TABLE `Ingredients` FOREIGN KEY (`component_id`) REFERENCES `Thing` (`id`);
要存储
东西的配方
,只需将其所有成分及其数量作为配料插入即可。要检索配方,只需选择具有该结果id的所有配料。要查看
东西
在配方中的使用位置,只需查询它作为组件的使用

假设
A
是由
B
C
构建的;而
B
可以由
D
E
构建。然后,您可能需要执行多阶段查询,从
a
=
B
+
C
中找出
a
=(
D
+
E
)+
C
。这需要对每个成分进行额外选择,以查看其本身是否含有成分。然而,除非你的食谱形成一棵树,否则这将适得其反:如果
a
需要
B
并且
B
可以从
a
构建,那该怎么办?。更糟糕的是:如果有几种方法可以获得
A
,比如从
B
+
C
或从
X
+
Y
?如果您需要区分这些可选配方,则需要一个附加表格:

struct东西{
病媒配方;
//…这里还有其他属性
};
结构配方{
std::载体成分;
//…这里还有其他属性
};
结构成分{
事物成分;
整数计数;
};
在SQL中

   CREATE TABLE `Recipes` (
      `id` int(11) NOT NULL AUTO_INCREMENT,           
      `result_id` int(11) NOT NULL, 
      PRIMARY KEY `id`
   );

   CREATE TABLE `Ingredients` (
      `id` int(11) NOT NULL AUTO_INCREMENT,           
      `recipe_id` int(11) NOT NULL, 
      `component_id` int(11) NOT NULL, 
      `count` int(11) NOT NULL,
      PRIMARY KEY `id`
   );

   ALTER TABLE `Recipes` FOREIGN KEY (`result_id`) REFERENCES `Thing` (`id`);
   ALTER TABLE `Ingredients` FOREIGN KEY (`recipe_id`) REFERENCES `Recipe` (`id`);
   ALTER TABLE `Ingredients` FOREIGN KEY (`component_id`) REFERENCES `Thing` (`id`);      
如果您需要在类似的内容上恢复多阶段配方,那么您将尝试在关系数据库上执行图形查询,并且可能会发现使用仅用于这些查询类型的对象图形数据库要容易得多


编辑:假设没有循环,并且每个
东西最多有一个食谱,我如何在给出配料列表的情况下找到要烹饪的食物?有几种方法是可能的

  • 如果菜谱的数量不是很大,而且菜谱也不会经常更改,只需将它们全部加载到内存中,并使用集合交集来检测可能的菜谱。这将比使用DB更快
  • 如果您坚持使用DB,这是可行的(您可以:
选择可能的.id
从(
选择i.result_id作为id,计数(*)作为总数
根据i.result\u id对“配料”进行分组
)尽可能(
选择结果id,计数(结果id)作为总数
从“配料”开始,我在哪里

(i.component_id=1和i.countSample数据、所需结果和适当的数据库标记都会有帮助。Oracle解析:如果要将集合存储为集合,可以:1)定义一个类型,该类型是集合或varray 2)使用您定义的列类型创建一个表。您将能够通过使用标准api从表中摄取对象。我正在寻找一种更通用的方法。因此,示例数据实际上在文章中,期望的结果也是如此。数据库的类型应该不太重要,但如果有帮助的话,我将使用mssql。这更像是一个问题逻辑问题:如何将其保存在关系数据库中,以及这种算法的大致工作原理。编辑:数据库中每个对象的条目都是其id和名称。@Pelle:您能更清楚地说明您的意图,并至少描述一下您的“对象”是如何工作的吗是复合的/相关的。它们应该支持哪些操作?仅将它们相加并与常量相乘?对象嵌套的深度有多深?是否允许循环关系?回答得很好!您非常理解我的问题。我将指定只有一个“配方”对于每个对象,因此将始终形成一棵树,这将排除所提到的复杂性。我看到你回答了找到每个包含特定成分的配方的方法,但是如果我有三种成分,一种配方只包含这三种成分,而另一种配方包含这三种成分,再加上一种成分,该怎么办呢那么配方出来了吗?这难道不比仅仅搜索它作为一个组件更复杂吗,因为它会在两个组件中都显示出来吗?我不理解你的问题/例子。如果你想要制作
a
所需的所有成分:
从result\u id='a'
的成分中选择*。事实是相同的成分可能对制作
C有用
D
不会使此无效,因为它们将具有
result\u id='C'
result\u id='D'
。我的意思是在我不知道结果会是b的情况下
SELECT possible.id 
    FROM (
        SELECT i.result_id AS id, COUNT(*) AS total
        FROM `Ingredients` AS i GROUP BY i.result_id
    ) AS possible, (
        SELECT result_id, COUNT(result_id) AS total
        FROM `Ingredients` AS i WHERE 
            (i.component_id = 1 AND i.count<=1) OR
            (i.component_id = 2 AND i.count<=3) OR
            (i.component_id = 42 AND i.count<=1)
        GROUP BY i.result_id
    ) AS valid
    WHERE possible.id = valid.result_id AND possible.total = valid.total;