SQL 计算 'reserved' 个库存项目的查询
SQL Query to calculates 'reserved' inventory items
我们正在为称为 readoutprobes 和 readoutprobekits 的项目创建库存系统。下面的模式被简化,使用 items 和 itemkits.
成套物品是 1 个或多个物品的预定义集合,即成套物品。在套件中,特定类型的物品只能出现一次。一个套件通常包含约 40 件物品。套件中项目的定义,由 itemkit_item table 捕获。套件的库存在 itemkit_containers table.
中捕获
itemkit_container不跟踪物理项目容器。相反,它假设物理物品包是正确的 'assembled',使用一组物理项目,但我们不知道是哪些。填充后,itemkit_containers 记录中的 'populated' 字段设置为 true。
物品 的库存由 item_containers table 跟踪。它的存在由容器卷监控。当体积为0时,容器被认为是空的。
从 item_container table 中获取特定物品的体积 > 0 的物理物品容器的数量,同样适用于套件
我们想为每个项目获得一个 'reserved count' 编号,以反映套件库存。
例如,假设我们有一个名为 A 的物品,其计数为 42。如果我们正在创建一个包含名为 A 的物品和对应的 itemkit_container 的物品包,我们希望有一个计数'reserved' 为 1,对于项目 A。
项目的 'master query' 如下所示:
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;
项目中的数据 table:
item_containers中的数据table:
物品包中的数据table:
itemkit_item中的数据table:
而itemkit_containers中的数据:
可以观察到,物品包及其库存的唯一记录包含物品 ID = {1,3}
这道题是想知道如何查询'free'(或预留)实体物品的数量,即有item_containers库存,在任何一个时间点。
上面的查询,returns这个结果:
我们需要一个附加字段,指示每个项目的 'Reserved' 计数,反映项目和项目包的实际库存状态。
对于上面的数据,这将是
A -> Reserved = 1
B -> Reserved = 0
C -> Reserved = 1
D -> Reserved = 0
创建并填充上述 table 的数据库 fiddle 位于此处:
DB Fiddle
我们正在使用 MySQL 8.0.
注意:以下答案接近正确。但是,它不会将 item_containers(实际库存)与 itemkit_container 记录相关联,而是将 itemkit 记录相关联。通过将 itemkit_containers table 中的填充字段切换为“0”,这一点变得很清楚。即:
即使不再填充套件,输出也会显示相同的 'Reserved' 计数。在这种情况下,保留应等于“0”。
这是针对这种情况的 fiddle:Fiddle where Reserved should be all '0'
感谢如此详细的描述和所有必要的示例数据。
正如您已经在查询中尝试过的那样,您可以通过加入项目和 item_containers table 来获得具有数量的项目。为了计算免费或保留的物品,您需要 left join itemkit_containsers table 因为套件中物品的库存存储在那里。因此,只需计算 itemkit_containers 中任何商品的数量,然后您就可以得到您的预留数量,然后从 item_containsers table 的 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);
查询:
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
name
total_volume
Reserved
1
A
2.00
0
2
B
1.00
0
3
C
1.00
0
4
D
1.00
0
dbhere
Db-Fiddle 填充和未填充 itemkit_containsers:
Select 查询(示例数据):
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
name
1
A
2
B
3
C
4
D
item_id
volume
1
1.00
2
1.00
3
1.00
4
1.00
1
1.00
id
name
1
Kit_1
2
Kit_2
itemkit_id
populated
1
0
2
1
itemkit_id
item_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
输出:
id
name
total_volume
Reserved
1
A
2.00
0
2
B
1.00
1
3
C
1.00
0
4
D
1.00
0
dbhere
添加了考虑 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
name
id
item_count
item_id
total_volume
Reserved
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;
我们正在为称为 readoutprobes 和 readoutprobekits 的项目创建库存系统。下面的模式被简化,使用 items 和 itemkits.
成套物品是 1 个或多个物品的预定义集合,即成套物品。在套件中,特定类型的物品只能出现一次。一个套件通常包含约 40 件物品。套件中项目的定义,由 itemkit_item table 捕获。套件的库存在 itemkit_containers table.
中捕获itemkit_container不跟踪物理项目容器。相反,它假设物理物品包是正确的 'assembled',使用一组物理项目,但我们不知道是哪些。填充后,itemkit_containers 记录中的 'populated' 字段设置为 true。
物品 的库存由 item_containers table 跟踪。它的存在由容器卷监控。当体积为0时,容器被认为是空的。
从 item_container table 中获取特定物品的体积 > 0 的物理物品容器的数量,同样适用于套件
我们想为每个项目获得一个 'reserved count' 编号,以反映套件库存。
例如,假设我们有一个名为 A 的物品,其计数为 42。如果我们正在创建一个包含名为 A 的物品和对应的 itemkit_container 的物品包,我们希望有一个计数'reserved' 为 1,对于项目 A。
项目的 'master query' 如下所示:
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;
项目中的数据 table:
item_containers中的数据table:
物品包中的数据table:
itemkit_item中的数据table:
而itemkit_containers中的数据:
可以观察到,物品包及其库存的唯一记录包含物品 ID = {1,3}
这道题是想知道如何查询'free'(或预留)实体物品的数量,即有item_containers库存,在任何一个时间点。
上面的查询,returns这个结果:
我们需要一个附加字段,指示每个项目的 'Reserved' 计数,反映项目和项目包的实际库存状态。
对于上面的数据,这将是
A -> Reserved = 1
B -> Reserved = 0
C -> Reserved = 1
D -> Reserved = 0
创建并填充上述 table 的数据库 fiddle 位于此处: DB Fiddle
我们正在使用 MySQL 8.0.
注意:以下答案接近正确。但是,它不会将 item_containers(实际库存)与 itemkit_container 记录相关联,而是将 itemkit 记录相关联。通过将 itemkit_containers table 中的填充字段切换为“0”,这一点变得很清楚。即:
即使不再填充套件,输出也会显示相同的 'Reserved' 计数。在这种情况下,保留应等于“0”。 这是针对这种情况的 fiddle:Fiddle where Reserved should be all '0'
感谢如此详细的描述和所有必要的示例数据。
正如您已经在查询中尝试过的那样,您可以通过加入项目和 item_containers table 来获得具有数量的项目。为了计算免费或保留的物品,您需要 left join itemkit_containsers table 因为套件中物品的库存存储在那里。因此,只需计算 itemkit_containers 中任何商品的数量,然后您就可以得到您的预留数量,然后从 item_containsers table 的 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);
查询:
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 | name | total_volume | Reserved |
---|---|---|---|
1 | A | 2.00 | 0 |
2 | B | 1.00 | 0 |
3 | C | 1.00 | 0 |
4 | D | 1.00 | 0 |
db
Db-Fiddle 填充和未填充 itemkit_containsers:
Select 查询(示例数据):
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 | name |
---|---|
1 | A |
2 | B |
3 | C |
4 | D |
item_id | volume |
---|---|
1 | 1.00 |
2 | 1.00 |
3 | 1.00 |
4 | 1.00 |
1 | 1.00 |
id | name |
---|---|
1 | Kit_1 |
2 | Kit_2 |
itemkit_id | populated |
---|---|
1 | 0 |
2 | 1 |
itemkit_id | item_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
输出:
id | name | total_volume | Reserved |
---|---|---|---|
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
.
查询:
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 | name | id | item_count | item_id | total_volume | Reserved |
---|---|---|---|---|---|---|
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;