用于计算“保留”库存项目的 SQL 查询

Tot*_*son 5 mysql sql inventory dbexpress sqlfiddle

我们正在为名为 readoutprobes 和 readoutprobekits 的项目创建一个库存系统。下面的模式使用itemsitemkits两个词进行了简化。

在此处输入图片说明

一个物品包,是一个或多个物品的预定义集合,即一个套件。在套件中,特定类型的物品只能出现一次。一个套件,通常包含约 40 件物品。套件中物品的定义由itemkit_item表捕获。套件的库存记录在itemkit_containers表中。

itemkit_container跟踪物理项目容器。相反,它假设使用一组物理项目正确地“组装”了一个物理项目包,但我们不知道是哪些。填充时,itemkit_containers 记录中的“填充”字段设置为 true。

物品的库存由item_containers表跟踪。它的存在由容器体积监控。当体积为 0 时,容器被认为是空的。

从item_container表中获取特定物品的体积> 0的物理物品容器的数量,对于套件也是如此

我们希望获得每个项目的“保留计数”编号,以反映套件库存。

例如,假设我们有一个名为 A 的项目,其计数为 42。如果我们正在创建一个包含名为 A 的项目和相应的 itemkit_container 的 itemkit,我们希望“reserved”的计数为 1,对于 item一种。

项目的“主查询”如下所示:

SELECT items.*,         
    ic.item_count
FROM items
LEFT JOIN (
    SELECT p.id, COUNT(*) item_count, ic.item_id
    FROM  items AS p, item_containers AS ic
    WHERE p.id = ic.item_id AND ic.volume > 0
    GROUP BY p.id
    ) AS ic   
    ON ic.item_id = items.id        
GROUP BY items.id    
ORDER BY items.id;
Run Code Online (Sandbox Code Playgroud)

项目表中的数据:

在此处输入图片说明

item_containers 表中的数据:

在此处输入图片说明

itemkits 表中的数据:

在此处输入图片说明

itemkit_item 表中的数据:

在此处输入图片说明

itemkit_containers 中的数据:

在此处输入图片说明

可以观察到,物品包及其库存的唯一记录包含物品 ID = {1,3}

这个问题是为了找出在任何一个时间点如何查询“空闲”(或保留)物理项目的数量,即 item_containers 存货。

上面的查询,返回这个结果:

在此处输入图片说明

我们需要一个额外的字段,指示每个项目的“保留”计数,反映项目和项目包的实际库存状态。

对于上面的数据,这将是

A -> Reserved = 1
B -> Reserved = 0
C -> Reserved = 1
D -> Reserved = 0
Run Code Online (Sandbox Code Playgroud)

创建和填充上述表格的 db fiddle 在这里: DB Fiddle

我们使用的是 MySQL 8.0。

注意:下面的答案接近正确。但是,它不会将 item_containers(实际库存)与 itemkit_container 记录相关联,而是与 itemkit 记录相关联。通过将 itemkit_containers 表中的填充字段切换为“0”,这一点变得清晰。IE:

在此处输入图片说明

即使套件不再填充,输出也会显示相同的“保留”计数。在这种情况下,保留应等于“0”。这是这种情况的小提琴Fiddle where Reserved should be all '0'

Kaz*_*Nur 2

感谢您提供如此详细的描述和所有必要的示例数据。

正如您已经在查询中尝试过的那样,您可以通过连接 items 和 item_containers 表来获得具有数量的项目。为了计算免费或保留的物品,您需要左连接 itemkit_containsers 表,因为套件中物品的库存存储在那里。因此,只需计算 itemkit_containers 中任何商品的数量,即可获得预留数量,并从 item_containsers 表的 item_count 中减去它,即可得到该商品的免费数量。

架构和插入语句:

 CREATE TABLE `items` (
   `id` int NOT NULL AUTO_INCREMENT,
   `name` varchar(512) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT 'oligoname + fluorophore wavelength',
   PRIMARY KEY (`id`)
 ) ENGINE=InnoDB AUTO_INCREMENT=1006 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='ReadoutProbes for mFISH Survey';
 
 CREATE TABLE `item_containers` (
   `id` int NOT NULL AUTO_INCREMENT,
   `item_id` int NOT NULL COMMENT 'content of tube',
   `volume` float(12,2) NOT NULL COMMENT 'volume in micro liter (uL)',
   PRIMARY KEY (`id`),
   KEY `fk_item_containers_items` (`item_id`),
   CONSTRAINT `fk_item_containers_items` FOREIGN KEY (`item_id`) REFERENCES `items` (`id`)
 ) ENGINE=InnoDB AUTO_INCREMENT=764 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='Physical tubes received from vendor';
 
 CREATE TABLE `itemkits` (
   `id` int NOT NULL AUTO_INCREMENT,
   `name` varchar(100) DEFAULT NULL,
   PRIMARY KEY (`id`),
   UNIQUE KEY `name` (`name`),
   UNIQUE KEY `Unique` (`name`)
 ) ENGINE=InnoDB AUTO_INCREMENT=1030 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='A readout kit is a collection of readouts, and defined in a codebook';
 
 CREATE TABLE `itemkit_containers` (
   `id` int NOT NULL AUTO_INCREMENT,
   `itemkit_id` int NOT NULL,
   `populated` tinyint(1) NOT NULL DEFAULT '0' COMMENT 'Field used for checking in checking out a tray',
   PRIMARY KEY (`id`),
   KEY `fk_readoutkit_tray_readoutkits` (`itemkit_id`),
   CONSTRAINT `fk_readoutkit_tray_readoutkits` FOREIGN KEY (`itemkit_id`) REFERENCES `itemkits` (`id`)
 ) ENGINE=InnoDB AUTO_INCREMENT=1027 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='Physical readoutkit_tray';
 
 CREATE TABLE `itemkit_item` (
   `itemkit_id` int NOT NULL,
   `item_id` int NOT NULL,
   UNIQUE KEY `Uniqueness` (`itemkit_id`,`item_id`),
   KEY `fk_readoutkit_item_readout_probes` (`item_id`),
   CONSTRAINT `fk_readoutkit_item_readout_probes` FOREIGN KEY (`item_id`) REFERENCES `items` (`id`),
   CONSTRAINT `fk_readoutkit_item_readoutkits` FOREIGN KEY (`itemkit_id`) REFERENCES `itemkits` (`id`)
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='associations table for definition of a readout kit';
       
 insert  into `items`(`id`,`name`) values 
 (1,'A'),
 (2,'B'),
 (3,'C'),
 (4,'D');
 
 insert  into `itemkits`(`id`,`name`) values 
 (1,'Kit_1');
 
 insert  into `itemkit_containers`(`itemkit_id`,`populated`) values 
 (1,0);
 
 insert  into `itemkit_item`(`itemkit_id`,`item_id`) values 
 (1,1),
 (1,3);
 
 insert  into `item_containers`(`item_id`,`volume`) values 
 (1,1.00),
 (2,1.00),
 (3,1.00),
 (4,1.00),
 (1,1.00);
 
Run Code Online (Sandbox Code Playgroud)

询问:

select i.id,i.name,sum(ic.volume) as total_volume,
      sum(coalesce(ii.item_count,0)) as Reserved 
      from items i inner join item_containers ic on i.id=ic.item_id
      left join (select item_id,count(*) as item_count from itemkit_containers ic
      inner join itemkit_item i on ic.itemkit_id =i.itemkit_id and ic.populated=1
      group by item_id) ii
      on i.id=ii.item_id
      group by i.id,i.name
      order by i.id,i.name
Run Code Online (Sandbox Code Playgroud)

输出:

ID 姓名 总容积 预订的
1 A 2.00 0
2 1.00 0
3 C 1.00 0
4 D 1.00 0

db<在这里小提琴

Db-Fiddle 包含已填充和未填充的 itemkit_containsers:

选择查询(示例数据):

 SELECT * from items;
 SELECT item_id, volume from item_containers;
 SELECT * FROM itemkits;
 SELECT itemkit_id, populated FROM itemkit_containers;
 SELECT * FROM itemkit_item;
Run Code Online (Sandbox Code Playgroud)

输出:

ID 姓名
1 A
2
3 C
4 D
商品编号 体积
1 1.00
2 1.00
3 1.00
4 1.00
1 1.00
ID 姓名
1 套件_1
2 套件_2
itemkit_id 人口稠密的
1 0
2 1
itemkit_id 商品编号
1 1
2 2
1 3

询问:

      select i.id,i.name,sum(ic.volume) as total_volume,
      sum(coalesce(ii.item_count,0)) as Reserved 
      from items i inner join item_containers ic on i.id=ic.item_id
      left join (select item_id,count(*) as item_count from itemkit_containers ic
      inner join itemkit_item i on ic.itemkit_id =i.itemkit_id and ic.populated=1
      group by item_id) ii
      on i.id=ii.item_id
      group by i.id,i.name
      order by i.id,i.name
Run Code Online (Sandbox Code Playgroud)

输出:

ID 姓名 总容积 预订的
1 A 2.00 0
2 1.00 1
3 C 1.00 0
4 D 1.00 0

db<在这里小提琴