Reputation: 462
My first post to stackoverflow (which has helped me hugely over time):
I have a query with a cross join that works fine when I run it with a where clause, but takes forever when I place it in a view and apply the where clause to the view.
I think the problem is that SQL is not applying the where clause to the cross join when the code is encapsulated in a view, and thus ending up with millions of rows (instead of 180 in this case).
The code is below - it is a query which forecasts the future on-hand stock of an item in a warehouse using an average expected monthly usage and a list of incoming orders.
CREATE VIEW [dbo].[ItemWarehouseStockForecastDaily2]
AS
SELECT
fd.AsafterDate
, iw.idItem
, iw.idWarehouse
, iw.OnHandQuantity
+ SUM(ISNULL(iwio.PurchaseOrderInboundQuantity, 0)
- iws.AverageMonthlyDemandQuantity / (365.25/12)
) OVER (ORDER BY fd.AsafterDate) AS OnHandQuantity
FROM
(
( SELECT CalendarDate Asafterdate
FROM Calendar c
WHERE c.CalendarDate > GETDATE()
AND c.CalendarDate < DATEADD(d, 180, GETDATE())
) fd -- This table has 180 rows
-- This table has 10 million rows - one per item per warehouse
CROSS JOIN ItemWarehouse iw
)
LEFT JOIN ItemWarehouseDemandFromStockStatisticsMonthly iws
ON iws.idItem = iw.idItem
AND iws.idWarehouse = iw.idWarehouse
LEFT JOIN ItemWarehouseInboundAndOutboundQuantitiesWithDueDate iwio
ON iwio.idItem = iw.idItem
AND iwio.idWarehouse = iw.idWarehouse
AND iwio.DueDate = fd.Asafterdate
/*
WHERE iw.idItem = 12345
AND iw.idWarehouse = 67
ORDER BY AsafterDate
*/
The commented-out where clause makes the query run fast (sub-second) when not in a view (tables cluster by idwarehouse, iditem)
Any/all help and advice will be greatly appreciated.
Upvotes: 1
Views: 792
Reputation: 882
I don't have the reputation to comment yet. However, checking on technet it says that a Cross Join should behave the same as a inner join if you add a where statement (at least for SQL 2008 R2). https://technet.microsoft.com/en-us/library/ms190690(v=sql.105).aspx
Did you check wether the same issue occurs if you use an inner join?
As another alternativ, can you add the constraint directly to the where clause as follows?
CREATE VIEW [dbo].[ItemWarehouseStockForecastDaily2]
AS
SELECT
fd.AsafterDate
, iw.idItem
, iw.idWarehouse
, iw.OnHandQuantity
+ SUM(ISNULL(iwio.PurchaseOrderInboundQuantity, 0)
- iws.AverageMonthlyDemandQuantity / (365.25/12)
) OVER (ORDER BY fd.AsafterDate) AS OnHandQuantity
FROM
(
( SELECT CalendarDate Asafterdate
FROM Calendar c
WHERE c.CalendarDate > GETDATE()
AND c.CalendarDate < DATEADD(d, 180, GETDATE())
) fd -- This table has 180 rows
-- Filter right here instead of later:
INNER JOIN ItemWarehouse iw ON iw.idItem = 12345 AND iw.idWarehouse = 67
)
LEFT JOIN ItemWarehouseDemandFromStockStatisticsMonthly iws
ON iws.idItem = iw.idItem
AND iws.idWarehouse = iw.idWarehouse
LEFT JOIN ItemWarehouseInboundAndOutboundQuantitiesWithDueDate iwio
ON iwio.idItem = iw.idItem
AND iwio.idWarehouse = iw.idWarehouse
AND iwio.DueDate = fd.Asafterdate
Upvotes: 0