SELECT it.uid,it.Name,COALESCE(sum(i.Qty),0)-COALESCE(sum(s.Qty),0) as stock
FROM items it
left outer join sales_items s on it.uid=s.ItemID
left outer join inventory i on it.uid=i.uid
group by s.ItemID,i.uid,it.UID;
这是我的查询。此查询需要59秒。如何加快查询速度?
我的桌子 - > 项目
UID Item
5089 JAM100GMXDFRUT
5090 JAM200GMXDFRUT
5091 JAM500GMXDFRUT
5092 JAM800GMXDFRUT
表格 - > sales_items
- slno ItemID Item Qty
- 9 5089 JAM100GMXDFRUT 5
- 10 5090 JAM200GMXDFRUT 2
- 11 5091 JAM500GMXDFRUT 1
表格 - > 库存
- slno uid Itemname Qty
- 102 5089 JAM100GMXDFRUT 10
- 200 5091 JAM500GMXDFRUT 15
- 205 5092 JAM800GMXDFRUT 20
此表有超过6000行
答案 0 :(得分:0)
将索引放在连接列
上sales_items ItemID
库存uid
答案 1 :(得分:0)
如果我正在设计这样的东西,我会有一个看起来像这样的查询和架构。记下我的Idx1索引。我不知道MySql,但是Sql Server会将这些索引用于sum函数,这称为覆盖查询。
select Item.ItemID, Item.Name, IsNull(sum(inv.Quantity), 0) - IsNull(sum(s.Quantity), 0) as stock
from Item
Left Join Inventory inv
On Item.ItemID = inv.ItemID
Left Join Sales s
On Item.ItemID = s.ItemID
Group by Item.ItemID, Item.Name
Create Table dbo.Location
(
LocationID int not null identity constraint LocationPK primary key,
Name NVarChar(256) not null
)
Create Table dbo.Item
(
ItemID int not null identity constraint ItemPK primary key,
Name NVarChar(256) not null
);
Create Table dbo.Inventory
(
InventoryID int not null identity constraint InventoryPK primary key,
LocationID int not null constraint InventoryLocationFK references dbo.Location(LocationID),
ItemID int not null constraint InventoryItemFK references dbo.Item(ItemID),
Quantity int not null,
Constraint AK1 Unique(LocationID, ItemID)
);
Create Index InventoryIDX1 on dbo.Inventory(ItemID, Quantity);
Create Table dbo.Sales
(
SaleID int not null identity constraint SalesPK primary key,
ItemID int not null constraint SalesItemFK references dbo.Item(ItemID),
Quantity int not null
);
Create Index SalesIDX1 on dbo.Sales(ItemID, Quantity);
答案 2 :(得分:0)
除了用于优化连接的表上的索引之外,您还使用S.ItemID进行分组而不仅仅使用IT.UID,因为这是连接基础,并且是查询的主FROM表的一部分...如果这是项目表上的可用索引,请使用它,您就完成了。无需通过。
引用组中的sales_items或库存列名称现在,正如所说的那样,你将遇到的另一个问题就是笛卡尔结果,如果你有相同的“物品ID”的多个记录,你从sales_items和库存中总结,因为我已经非常简化了一个例子,通过
CREATE TABLE items (
`uid` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(5) NOT NULL,
PRIMARY KEY (`uid`)
);
CREATE TABLE sales_items (
`sid` int(11) NOT NULL AUTO_INCREMENT,
`itemid` int(11),
`qty` int(5) NOT NULL,
PRIMARY KEY (`sid`),
KEY byItemAndQty (`itemid`,`qty`)
);
CREATE TABLE inventory (
`iid` int(11) NOT NULL AUTO_INCREMENT,
`uid` int(11) NOT NULL,
`qty` int(5) NOT NULL,
PRIMARY KEY (`iid`),
KEY byItemAndQty (`itemid`,`qty`)
);
insert into items ( uid, name ) values ( 1, 'test' );
INSERT INTO sales_items ( sid, itemid, qty ) VALUES ( 1, 1, 1 );
INSERT INTO sales_items ( sid, itemid, qty ) VALUES ( 2, 1, 2 );
INSERT INTO inventory ( iid, uid, qty ) VALUES ( 1, 1, 13 );
INSERT INTO inventory ( iid, uid, qty ) VALUES ( 2, 1, 35 );
简单1项, 销售项目2项目1的记录。数量为1和2,总数= 3 第1项的库存2记录.13和35的数量,共计38
SELECT
it.uid,
it.Name,
sum(i.Qty) as iQty,
sum(s.Qty) as sQty,
COALESCE( sum(i.Qty),0) - COALESCE(sum(s.Qty),0) as stock
FROM
items it
left outer join sales_items s
on it.uid = s.ItemID
left outer join inventory i
on it.uid = i.uid
group by
it.uid
因此,您可能希望股票的查询结果为
uid name iQty sQty stock
1 test 48 3 45
but in reality becomes
1 test 96 6 90
现在......请注意我的假设,但是从这样的多个表中看到类似的sum()s或count()s。我假设ITEMS表是每个项目一个记录 Sales_Items实际上具有比提供的列更多的列(例如销售详细信息和可以跟踪的每个日期/销售计数),并且可以包含给定项目ID的多个销售记录数量(从而匹配我的样本)。最后,Inventory表同样可以每个相同项目有多个记录,例如按日期跟踪的传入库存的购买,以及每个给定项目ID的多个记录(也与我的示例匹配)。
为了防止这种类型的笛卡尔结果,并且还可以提高速度,我会对每个辅助表进行预聚合并加入到该表中。
SELECT
it.uid,
it.Name,
i.iQty,
s.sQty,
COALESCE( i.iQty,0) - COALESCE(s.sQty,0) as stock
FROM
items it
left join ( select itemid, sum( qty ) as SQty
from sales_items
group by itemid ) s
on it.uid = s.ItemID
left join ( select uid, sum( qty ) as IQty
from inventory
group by uid ) i
on it.uid = i.uid
group by
it.uid
你得到正确的
值uid name iQty sQty stock
1 test 48 3 45
是的,这只是针对单个商品ID来证明这一点,但仍然适用于您拥有的库存商品数量以及某些商品可能(或不存在)的相应销售/库存记录。