亲爱的,我正在打电话给谁可以解决任何SQL查询性能问题
我正在生成一份库存报告,用于处理库存商品的位置,我想向用户显示一个标记“不再可用”,这意味着该位置不可用,因为它是从另一个商品中获取的。
主要是这部分代码完成的。使用以下条件:
IIF(ItemLocationsCount > 1 and ItemsInStock = 0 and StoreId <> MainStoreId, 'Not available any more', Store)
此情况仅针对具有多个位置且数量为 0 的商品(ItemsInStock 列)显示该标志
此聚合正在计算某个项目所占用的位置数量:
ItemsInStockByCurrentItemLocation as (
select *
,( select
count(*)
from
ItemsInStock ItemsInStockLocationsCount
where
ItemsInStock.StoreId = ItemsInStockLocationsCount.StoreId
group by MainStoreId) ItemLocationsCount
from
ItemsInStock
)
这是显示带有所需标志的整个数据的视图(运行太慢了 30 分钟):
,FilteredUnitifiedConsederingLocation as (
select (select
IIF(ItemLocationsCount > 1 and ItemsInStock = 0 and StoreId <> MainStoreId, 'Not available any more', Store)
from
ItemsInStockByCurrentItemLocation ItemsInStockByCurrentItemLocationAvalability
where
ItemsInStockByCurrentItemLocationAvalability.StoreId = ItemsInStockByCurrentItemLocation.StoreId and
ItemsInStockByCurrentItemLocationAvalability.ItemId = ItemsInStockByCurrentItemLocation.ItemId) StoreAvalability,
ItemsInStockByCurrentItemLocation.*,
MainAndWorkFlowUnitified.Date_P,
MainAndWorkFlowUnitified.Date
from ItemsInStockByCurrentItemLocation
inner join MainAndWorkFlowUnitified
on MainAndWorkFlowUnitified.StoreId = ItemsInStockByCurrentItemLocation.StoreId and
MainAndWorkFlowUnitified.ItemId = ItemsInStockByCurrentItemLocation.ItemId
where
--(ItemLocationsCount = 1 or
--(ItemLocationsCount > 1 and ItemsInStock <> 0)) and
(ItemsInStockByCurrentItemLocation.StorePath Like '%' + @StorePath + '%'
or (ItemsInStockByCurrentItemLocation.StorePath is null and MSId is not null))
and ItemsInStockByCurrentItemLocation.ItemPath Like @ItemPath + '%'
and (ItemsInStockByCurrentItemLocation.Description is null or ItemsInStockByCurrentItemLocation.Description like '%' + @Description + '%' )
and (Date_P is null or (Date >= @FromDate and Date <= @ToDate))
)
这是显示整个数据的视图,没有生成所需标志的部分(这运行得太快了 1 秒):
,FilteredUnitified as (
select ItemsInStock.*,
MainAndWorkFlowUnitified.Date_P,
MainAndWorkFlowUnitified.Date
from ItemsInStock
inner join MainAndWorkFlowUnitified
on MainAndWorkFlowUnitified.StoreId = ItemsInStock.StoreId and
MainAndWorkFlowUnitified.ItemId = ItemsInStock.ItemId
where
(ItemsInStock.StorePath Like '%' + @StorePath + '%'
or (ItemsInStock.StorePath is null and MSId is not null))
and ItemsInStock.ItemPath Like @ItemPath + '%'
and (ItemsInStock.Description is null or ItemsInStock.Description like '%' + @Description + '%' )
and (Date_P is null or (Date >= @FromDate and Date <= @ToDate))
)
这是在参数值上两者之间发生变化的视图:
ItemsInStocks as (
select
distinct
ItemId,
ParentGroup,
Unit,
Item, ItemPath,
StoreAvalability Store,
ItemLocationsCount,
MainStorePath,
--Store,
StorePath,
ItemsInStock,
Description
,Code,
Name,
NameEn
from FilteredUnitifiedConsederingLocation where @ShowItemsWithUnavailableLocations = 1
union all
select
distinct
ItemId,
ParentGroup,
Unit,
Item, ItemPath,
Store,
null ItemLocationsCount,
MainStorePath,
StorePath,
ItemsInStock,
Description
,Code,
Name,
NameEn
from FilteredUnitified where @ShowItemsWithUnavailableLocations = 0
我尝试不显示该行,而是放置一个标志。 (可以看相关代码注释)
--(ItemLocationsCount = 1 or
--(ItemLocationsCount > 1 and ItemsInStock <> 0))
但同样的事情正在发生。视图仍然运行太慢
我查阅了知识库中的相关问题,发现有一个建议使用索引: 我认为所有必需的列都像 ItemId、StoreId 和 MainStoreId 一样被索引,因为它们是外键。请注意,如果需要对任何其他列进行索引以优化性能,请告诉我。
首先,您的查询应使用
table.column
或 alias.column
进行格式化,以便用户知道数据来自哪里,而不是猜测哪一列。例如,拥有 VeryLongTableName
会变得模糊,而 VeryLongTableName vltn
更容易通过别名 vltn
来表示。如果您只查询单个表,则没有必要。
我将从每个商店的商品预查询开始。谁在乎有多少,只要它存在,通过对 ItemsInStock > 0 应用 WHERE 子句,您就已经排除了那些不符合条件的产品。
我怀疑无论 MainStoreID 如何,StoreID 都是唯一的,否则数据库关系中的设计会更加可疑,因此出于冗余目的将其保留。但是,您还引用了 MSId 列。 MSId 是“MainStoreID”吗?如果是这样,请不要通过提供两个列名称上下文来混淆问题,或者至少像前面提到的那样通过别名进行澄清。
现在,进入你的WHERE子句,两边都带有通配符的LIKE不能利用任何索引进行优化,它必须扫描每条记录
ItemsAvailablePerStore as
(
select distinct
StoreID,
ItemId
from
ItemsInStock
where
ItemsInStock > 0
),
现在,我将使用您的主 ItemsInStock 表开始查询,左连接到仅具有现有数量的结果,然后从那里开始。与您的物品描述类似。进一步阅读这个问题,我真的很怀疑数据库的设计得有多好,但仍然愿意提供帮助。下次可以协助设计问题。
AllItems as
(
select
IIS.*,
case when ISA.StoreId is null
then 'Not available any more'
else ' ' end StoreAvailability,
MWF.Date_P,
MWF.Date
from
ItemsInStock IIS
LEFT JOIN ItemsAvailablePerStore IAPS
on IIS.StoreId = IAPS.StoreID
and IIS.ItemID = IAPS.ItemID
JOIN MainAndWorkFlowUnitified MWF
on IIS.StoreID = MWF.StoreId
and IIS.ItemID = MWF.ItemId
where
( IIS.StorePath Like '%' + @StorePath + '%'
or ( IIS.StorePath is null and IIS.MainStoreId is not null)
)
and IIS.ItemPath Like @ItemPath + '%'
and (IIS.Description is null or IIS.Description like '%' + @Description + '%' )
and (MWF.Date_P is null or ( MWF.Date >= @FromDate and MWF.Date <= @ToDate))
)