Reputation: 31
First, I apologize if this has been answered elsewhere, but I was unable to find anything today. If it has been answered, the lack is me, not the search system.
I am having an issue where in a stored procedure works fairly quickly until I get to a specific point.
I have a database of POS sales data for a restaurant chain.
Among the various tables we have, the ones I need for this query are:
Item (the definitions of the various items; each row includes the SALES category the item belongs to; see caveats below)
Category (the definitions of the various categories items can be in)
CategoryItem (the mapping between the above)
HstItem (the historical sales of the items)
Caveats: There are 2 types of categories each item can be in:
sales categories: each item can be in one sales category at a time.
reporting categories: each item can be in a arbitrary number of these categories simultaneously.
I am needing to get sales totals for 6 date ranges for a specific REPORTING category (week to date, wtd ly, period to date, ptd ly, year to date, ytd ly).
All of that said, for all of my code the query / procedure runs in a decent amount of time, until to the section for the reporting category.
My select statement currently includes the following WHERE clause:
where hstitem.itemid in (select fkitemid from categoryitem where categoryitemid = ##)
I am looking for a more efficient / faster way to execute this.
Any assistance is greatly appreciated. Thanks in advance.
EDIT:
The full original query is as follows:
insert into #GnG (GStoreID, CurWkGNG, CurWkGNGLY,CurYTDGNG,CurYTDGNGLY,CurrPTDGNG,CurrPTDGNGLY)
select
hgi.FKStoreId,
CurWkGnG = sum(case when hgi.DateOfBusiness between @SDate and @EDate then hgi.price else 0 end),
CurWkGnGLY = sum(case when hgi.DateOfBusiness between @SDateLY and @EDateLY then hgi.price else 0 end),
CurYTDGnG =
case
when convert(varchar(10),opendate,126) between convert(varchar(10),@LYTDStart,126) and convert(varchar(10),@LYTDEnd,126) then sum(case when hgi.DateOfBusiness between DATEADD(day, (DATEPART(week, opendate) * 7 + DATEPART(weekday, opendate)) - (DATEPART(week, DATEADD(year, 1, opendate)) * 7 + DATEPART(weekday, DATEADD(year, 1, opendate))), DATEADD(year, 1, opendate)) and @CYTDEnd then hgi.price else 0 end)
else sum(case when hgi.DateOfBusiness between @CYTDStart and @CYTDEnd then hgi.price else 0 end)
end,
CurYTDGnGLY = sum(case when hgi.DateOfBusiness between @LYTDStart and @LYTDEnd then hgi.price else 0 end),
CurrPTDGnG = sum(case when hgi.DateOfBusiness between @CurrPtDStart and @CurrPtDEnd then hgi.price else 0 end),
CurrPTDGnGLY = sum(case when hgi.DateOfBusiness between @CurrPtDLYStart and @CurrPtDlyEnd then hgi.price else 0 end)
from hstGndItem hgi
join #StoresIncluded si
on hgi.FKStoreID = si.StoreID
where hgi.fkitemid in
(select fkitemid from categoryitem where categoryitemid = 25)
group by hgi.fkstoreid, opendate, comping
order by hgi.fkstoreid
Upvotes: 1
Views: 85
Reputation: 31
I apologize for the lag in my response here. I found AN answer. Dont know if it is the right one or not, but it works for us. I removed the code to use a sub select from the where, and am now generating a new table to hold the values that should pull. The new code to populate the table runs each morning around 0600. I then am having the main code simply join to that table to pull the single answer, rather than perform math based on the sub-query.
Thank you all for the suggestions.
Upvotes: 0
Reputation: 1223
You can use WHERE EXISTS
instead of IN
to check if the ID exists in the table:
WHERE EXISTS
(
SELECT ci.fkitemid
FROM categoryitem ci
WHERE ci.categoryitemid = ## AND ci.fkitemid = hstitem.itemid
)
The difference between the IN
clause and using EXISTS
is that the sub-query inside the WHERE EXISTS
will exit prematurely after a match have been found while the IN
clause would wait until the sub-query is finished.
Upvotes: 0
Reputation: 1783
Try converting the "IN" to a inner join like so :
FROM hstitem h inner join categoryitem c on c.fkitemid = h.itemid
where c.categoryitemid = ##
Upvotes: 1