如何解决用于计算“保留”库存项目的 SQL 查询
我们正在为名为 readoutprobes 和 readoutprobekits 的项目创建一个库存系统。下面的架构使用items 和itemkits 这两个词进行了简化。
一个物品套件,是一个或多个物品的预定义集合,即套件。在套件中,特定类型的物品只能出现一次。一个套件,通常包含约 40 件物品。套件中物品的定义由 itemkit_item 表捕获。套件的库存记录在 itemkit_containers 表中。
itemkit_container 不跟踪物理项目容器。相反,它假设使用一组物理项目正确“组装”了一个物理项目包,但我们不知道是哪些。填充后,itemkit_containers 记录中的“填充”字段设置为 true。
items 的库存由item_containers 表跟踪。它的存在由容器体积监控。当volume为0时,容器被认为是空的。
从item_container表中获取特定物品的体积> 0的物理物品容器的数量,对于套件也是如此
我们希望获得每个项目的 'reserved count' 编号,以反映套件库存。
例如,假设我们有一个名为 A 的项目,其计数为 42。如果我们正在创建一个包含名为 A 的项目和相应的 itemkit_container 的 itemkit,我们希望“保留”的计数为 1,对于项目 A。
项目的“主查询”如下所示:
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;
items 表中的数据:
item_containers 表中的数据:
itemkits 表中的数据:
itemkit_item 表中的数据:
以及 itemkit_containers 中的数据:
正如所观察到的,物品包的唯一记录及其库存包含物品 ID = {1,3} 的物品
这个问题是为了找出如何查询“空闲”(或保留)物理项目的数量,即在任何时间点的 item_containers 库存。
上面的查询,返回这个结果:
我们想要一个额外的字段,用于指示每个项目的“保留”计数,反映项目和项目包的实际库存状态。
对于上面的数据,这将是
A -> Reserved = 1
B -> Reserved = 0
C -> Reserved = 1
D -> Reserved = 0
创建和填充上述表格的 db fiddle 在这里: DB Fiddle
我们使用的是 MySQL 8.0。
注意:下面的答案接近正确。但是,它不会将 item_containers(实际库存)与 itemkit_container 记录相关联,而是与 itemkit 记录相关联。通过将 itemkit_containers 表中的填充字段切换为“0”,这一点变得清晰。即:
即使套件不再填充,输出也会显示相同的“保留”计数。在这种情况下,保留应等于“0”。 这是这种情况的小提琴:Fiddle where Reserved should be all '0'
解决方法
感谢如此详细的描述和所有必要的示例数据。
正如您在查询中已经尝试过的那样,您可以通过连接 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,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',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`,'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),1.00);
查询:
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
输出:
id | 名称 | total_volume | 保留 |
---|---|---|---|
1 | A | 2.00 | 0 |
2 | B | 1.00 | 0 |
3 | C | 1.00 | 0 |
4 | D | 1.00 | 0 |
db
带有填充和未填充 itemkit_containsers 的 Db-Fiddle:
选择查询(示例数据):
SELECT * from items;
SELECT item_id,volume from item_containers;
SELECT * FROM itemkits;
SELECT itemkit_id,populated FROM itemkit_containers;
SELECT * FROM itemkit_item;
输出:
id | 名称 |
---|---|
1 | A |
2 | B |
3 | C |
4 | D |
item_id | 音量 |
---|---|
1 | 1.00 |
2 | 1.00 |
3 | 1.00 |
4 | 1.00 |
1 | 1.00 |
id | 名称 |
---|---|
1 | Kit_1 |
2 | Kit_2 |
itemkit_id | 已填充 |
---|---|
1 | 0 |
2 | 1 |
itemkit_id | item_id |
---|---|
1 | 1 |
2 | 2 |
1 | 3 |
查询:
select i.id,i.name
输出:
id | 名称 | total_volume | 保留 |
---|---|---|---|
1 | A | 2.00 | 0 |
2 | B | 1.00 | 1 |
3 | C | 1.00 | 0 |
4 | D | 1.00 | 0 |
db
添加了考虑 populated column of itemkit_containers
并为 reserved counts
提供正确输出的 sql 语句。
查询:
SELECT items.*,ic.*,v.total_volume,COALESCE(item_in_kit.item_count,0) AS Reserved
FROM items
LEFT JOIN (
SELECT i.id,COUNT(*) item_count,ic.item_id
FROM items AS i,item_containers AS ic
WHERE i.id = ic.item_id AND ic.volume > 0
GROUP BY i.id
) AS ic
ON ic.item_id = items.id
LEFT JOIN (
SELECT items.id,COALESCE(SUM(ic.volume),0) total_volume
FROM items,item_containers AS ic
WHERE items.id = ic.item_id
GROUP BY items.id
) AS v
ON items.id = v.id
LEFT JOIN item_containers
ON item_containers.item_id = items.id
LEFT JOIN (
SELECT item_id,COUNT(*) AS item_count
FROM itemkit_item where itemkit_id not in
(select itemkit_id from itemkit_containers where populated = 0)
GROUP BY item_id
) item_in_kit
ON items.id = item_in_kit.item_id
GROUP BY items.id
ORDER BY items.id;
输出:
id | 姓名 | id | item_count | item_id | total_volume | 保留 |
---|---|---|---|---|---|---|
1 | A | 1 | 2 | 1 | 2.00 | 0 |
2 | B | 2 | 1 | 2 | 1.00 | 0 |
3 | C | 3 | 1 | 3 | 1.00 | 0 |
4 | D | 4 | 1 | 4 | 1.00 | 0 |
首先计算总数并从适当的容器中保留,然后左连接总数并保留到项目。
SELECT items.id,items.name,coalesce(total.v,0) AS Total_volume,coalesce(rsvd.v,0) AS Reserved
FROM items
LEFT JOIN ( /* item total in item_containers */
SELECT item_id,SUM(volume) v
FROM item_containers
GROUP BY item_id
) AS total ON items.id = total.item_id
LEFT JOIN( /* item reservation by itemkit_containers */
SELECT iki.item_id,count(*) v
FROM itemkit_containers AS ic
JOIN itemkit_item AS iki
ON ic.itemkit_id = iki.itemkit_id AND ic.Populated = 1
GROUP BY iki.item_id
) AS rsvd ON items.id = rsvd.item_id
ORDER BY items.id;
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。