database - 从导入的规则生成集

标签 database algorithm

题目很不精确,但我想避免把整个问题都抄进去。这些集合实际上是如第一节所述的映射,规则在第二节中出现,问题是生成所有内容将意味着如最后一节所述的太多数据。
当前状态
目前有几十个,很快就有几百个Customers。每个Items可能有几千个Catalogs和数千个m:ns。每个项目和每个目录都属于一个客户,不同客户的数据不交互。
项目和目录之间存在catalog1关系。我将目录视为重叠的项集,并且还有一些其他相关的详细信息数据来自一个导入文件,看起来像

catalog1 item1 details11
catalog1 item3 details13
catalog2 item1 details12
catalog2 item2 details22

在数据库中,有一个具有三列的连接表,就像导入文件一样。
在本例中,我将{item1: details11, item3: details13}的内容检索为Item等。检索此表单中目录的内容是唯一重要的查询到目前为止,这还很微不足道。
导入每天发生几次,我必须相应地更新数据库内容。导入是部分的,因为总是只导入单个客户的数据,这意味着总是只导入
一部分数据会受到影响导入是完全的,因为导入文件包含给定客户的所有数据,所以我必须添加新的内容、更新更改的内容并删除新导入文件中缺少的内容。还是很琐碎的。
新要求
现在,小组将被引入每个ItemGroup都可以是多个Catalogs的成员,每个CatalogGroup都可以是多个Detailss的成员。这些信息是单独提供的,并且导入格式几乎没有变化:在目录中,可以有目录组,在项目中,可以有项目组。
所以有些规则像
catalog1 item1 details100
catalogGroup1 item1 details101
catalog1 itemGroup1 details102
catalogGroup1 itemGroup1 details102

代替简单的连接表行这些规则可能会冲突,也会冲突,我目前倾向于通过优先于先前的规则来解决冲突(导入文件的制作者将接受我的决定)。
catalog1中,可能有一条信息指出相应的项应该从目录中排除,例如
catalog1 item1 EXCLUDE
catalog1 itemGroup1 someDetails

意味着itemGroup1包含item1中除catalog之外的所有项(第一条规则获胜)。
问题
我们的连接表已经有将近一百万行了,我们才刚刚开始如果没有新的需求,它可能会增长到几亿行,这是可以接受的。
随着新的需求,这个数字可能增长得更快,因此存储连接表可能是不可行的。现在,这个表占用的磁盘空间已经超过了所有剩余的磁盘空间。编写一个错误生成数百万行的规则也相当容易(这肯定有一天会发生)。
我们所需要的是能够相当快地检索目录的内容,也就是说,当目录包含数百个项目时,不到半秒到目前为止,我们还不需要存储表,使用索引和一些简单的后处理的一些连接应该是可以的。
很多目录根本不会被查询,但这没有帮助,因为我们不知道是哪一个。
进口不必很快。目前,他们需要一两秒钟,但几分钟是可以接受的。
因此,我想知道我是否应该创建四个表,一个用于catalogGroupitemitemGroup的组合。每个表还将包含导入文件中的行号,以便检索与请求的目录匹配的所有规则,并在后处理中解决冲突。
或者是更简单的解决方案?我有点想做一张桌子
catalog, catalogGroup, item, itemGroup, lineNo, details_part1, details_part2, ...

(总是使用前四列中的两列)因为细节实际上是几个部分的元组,这使得四个表非常重复。我可以在一个新表中提取细节,或者把它们放在一起。
我在找一些如何有效处理它的一般性建议。
我想,有些细节是缺失的,但问题已经太长了。请随便问。它是一个使用java、hibernate和mysql的web应用程序,但是由于它不重要,所以省略了标记。
对评论的答复
是否仍在查询目录内容?
是的,和以前一样。这些组是某种输入压缩,仅此而已。
如果项连接到目录或包含查询目录的组,则返回该项?
或是这样一个团体的成员。
项目组如何工作?
两种类型的组工作相同:
包含组的规则相当于规则列表,每个组成员一个。

最佳答案

我建议从规范化的表和一个简单的连接开始。如果我没看错你的问题,这里有一个合理的方案:

CREATE TABLE items (
  id integer PRIMARY KEY,
  name varchar(40)
);

CREATE TABLE catalogs (
  id integer PRIMARY KEY,
  name varchar(40)
);

CREATE TABLE item_groups (
  id integer PRIMARY KEY,
  name varchar(40)
);

CREATE TABLE catalog_groups (
  id integer PRIMARY KEY,
  name varchar(40)
);

CREATE TABLE items_in_groups (
  item_id integer REFERENCES items(id),
  item_group_id integer REFERENCES item_groups(id),
  PRIMARY KEY(item_id, item_group_id)
);

CREATE TABLE catalogs_in_groups (
  catalog_id integer REFERENCES catalogs(id),
  catalog_group_id integer REFERENCES catalog_groups(id),
  PRIMARY KEY(catalog_id, catalog_group_id)
);

CREATE TABLE exclusions (
  catalog_id integer REFERENCES catalogs(id),
  item_id integer REFERENCES items(id),
  PRIMARY KEY(catalog_id, item_id)
);

CREATE TABLE connections (
  catalog_group_id integer REFERENCES catalog_groups(id),
  item_group_id integer REFERENCES item_groups(id),
  details varchar(40),
  PRIMARY KEY(catalog_group_id, item_group_id)
);

注意items_in_groupscatalogs_in_groups分别为每个项目和目录获取一个单独的条目也就是说,每个项都由一个元素组表示,对于目录也是这样。
现在添加一些数据:
INSERT INTO items VALUES (1, 'Item 1'), (2, 'Item 2'), (3, 'item 3'), (4, 'item 4'), (5, 'item 5'), (6, 'item 6');
INSERT INTO catalogs VALUES (1, 'Catalog 1'), (2, 'Catalog 2'), (3, 'Catalog 3'), (4, 'Catalog 4'),
  (5, 'Catalog 5'), (6, 'Catalog 6');

INSERT INTO item_groups VALUES
  (1, 'Item group 1'), (2, 'Item group 2'), (3, 'Item group 3'), (4, 'Item group 4'), (5, 'Item group 5'),
  (6, 'Item group 6'), (10, 'Item group 10'), (11, 'Item group 11'), (12, 'Item group 12');

INSERT INTO catalog_groups VALUES
  (1, 'Catalog group 1'), (2, 'Catalog group 2'), (3, 'Catalog group 3'), (4, 'Catalog group 4'), 
  (5, 'Catalog group 5'), (6, 'Catalog group 6'), (10, 'Catalog group 10'), (11, 'Catalog group 11'),
  (12, 'Catalog group 12');

INSERT INTO items_in_groups VALUES
  (1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6), (2, 10), (4, 10),
  (6, 10), (1, 11), (3, 11), (5, 11), (1, 12), (2, 12), (3, 12), (6, 12);

INSERT INTO catalogs_in_groups VALUES
  (1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6), (2, 11), (4, 11),
  (6, 11), (1, 10), (3, 10), (5, 10), (3, 12), (4, 12), (5, 12), (6, 12);

INSERT INTO exclusions VALUES (5, 1), (6, 3);

INSERT INTO connections VALUES (1, 10, 'Details 1-10'), (11, 2, 'Details 11-2'), (12, 12, 'Details 12-12');

以及查询:
SELECT cig.catalog_id, iig.item_id, c.details FROM connections AS c
INNER JOIN item_groups AS ig ON c.item_group_id = ig.id
INNER JOIN catalog_groups AS cg ON c.catalog_group_id = cg.id
INNER JOIN items_in_groups AS iig ON iig.item_group_id = ig.id
INNER JOIN catalogs_in_groups AS cig ON cig.catalog_group_id = cg.id
WHERE NOT EXISTS (
  SELECT NULL
  FROM exclusions e
  WHERE iig.item_id = e.item_id AND cig.catalog_id = e.catalog_id)
ORDER BY cig.catalog_id, iig.item_id;

结果是:
 catalog_id | item_id |    details
------------+---------+---------------
          1 |       2 | Details 1-10
          1 |       4 | Details 1-10
          1 |       6 | Details 1-10
          2 |       2 | Details 11-2
          3 |       1 | Details 12-12
          3 |       2 | Details 12-12
          3 |       3 | Details 12-12
          3 |       6 | Details 12-12
          4 |       1 | Details 12-12
          4 |       2 | Details 11-2
          4 |       2 | Details 12-12
          4 |       3 | Details 12-12
          4 |       6 | Details 12-12
          5 |       2 | Details 12-12
          5 |       3 | Details 12-12
          5 |       6 | Details 12-12
          6 |       1 | Details 12-12
          6 |       2 | Details 11-2
          6 |       2 | Details 12-12
          6 |       6 | Details 12-12
(20 rows)

您可以将itemscatalogs添加到连接以查找各自的名称,而不是使用id停止。
SELECT cat.name, item.name, c.details FROM connections AS c
INNER JOIN item_groups AS ig ON c.item_group_id = ig.id
INNER JOIN catalog_groups AS cg ON c.catalog_group_id = cg.id
INNER JOIN items_in_groups AS iig ON iig.item_group_id = ig.id
INNER JOIN catalogs_in_groups AS cig ON cig.catalog_group_id = cg.id
INNER JOIN catalogs AS cat ON cat.id = cig.catalog_id
INNER JOIN items AS item ON item.id = iig.item_id
where NOT EXISTS (
  SELECT NULL
  FROM exclusions e
  WHERE iig.item_id = e.item_id AND cig.catalog_id = e.catalog_id)
ORDER BY cig.catalog_id, iig.item_id;

就像这样。。。
   name    |  name  |    details    
-----------+--------+---------------
 Catalog 1 | Item 2 | Details 1-10
 Catalog 1 | item 4 | Details 1-10
 Catalog 1 | item 6 | Details 1-10
 Catalog 2 | Item 2 | Details 11-2
 Catalog 3 | Item 1 | Details 12-12
 Catalog 3 | Item 2 | Details 12-12
 Catalog 3 | item 3 | Details 12-12
 Catalog 3 | item 6 | Details 12-12
 Catalog 4 | Item 1 | Details 12-12
 Catalog 4 | Item 2 | Details 11-2
 Catalog 4 | Item 2 | Details 12-12
 Catalog 4 | item 3 | Details 12-12
 Catalog 4 | item 6 | Details 12-12
 Catalog 5 | Item 2 | Details 12-12
 Catalog 5 | item 3 | Details 12-12
 Catalog 5 | item 6 | Details 12-12
 Catalog 6 | Item 1 | Details 12-12
 Catalog 6 | Item 2 | Details 11-2
 Catalog 6 | Item 2 | Details 12-12
 Catalog 6 | item 6 | Details 12-12
(20 rows)

如您所见,存在具有各自详细信息的重复目录/项ID对我想这就是您所说的“冲突”的意思,调整查询以遵循优先级规则来选择一个备选方案并不难。
获取特定目录的项只是一个额外的AND原因:
SELECT cat.name, item.name, c.details FROM connections AS c
INNER JOIN item_groups AS ig ON c.item_group_id = ig.id
INNER JOIN catalog_groups AS cg ON c.catalog_group_id = cg.id
INNER JOIN items_in_groups AS iig ON iig.item_group_id = ig.id
INNER JOIN catalogs_in_groups AS cig ON cig.catalog_group_id = cg.id
INNER JOIN catalogs AS cat ON cat.id = cig.catalog_id
INNER JOIN items AS item ON item.id = iig.item_id
WHERE NOT EXISTS (
  SELECT NULL
  FROM exclusions e
  WHERE iig.item_id = e.item_id AND cig.catalog_id = e.catalog_id)
AND cat.id = 3
ORDER BY cig.catalog_id, iig.item_id;

还有…
   name    |  name  |    details    
-----------+--------+---------------
 Catalog 3 | Item 1 | Details 12-12
 Catalog 3 | Item 2 | Details 12-12
 Catalog 3 | item 3 | Details 12-12
 Catalog 3 | item 6 | Details 12-12
(4 rows)

和往常一样,还有其他几种方法来编写查询我不是SQL向导,但有很多。如果第一次黑客攻击不够好,回来问问去正规化和疯狂的前处理和后处理方案将去掉未来的灵活性。

关于database - 从导入的规则生成集,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45404417/

相关文章:

sql - 数据库版本控制——如何回到以前的版本并保留数据?

c++ - C++ 的开源 Graph 类

c - 段错误(核心已转储)C

algorithm - hash解密,可以用什么算法

java - 从 2 个字符串中删除重复字符

asp.net - SQL Server,连接池与特殊情况下的静态连接

mysql - SQL InitCap表示一些特殊单词大写

database - 不能在oracle中删除表空间

SQL Server - 从数据中删除结束字符串字符 "\0"

Python形态学n_ary_converter