OK , i got it, the new version of my stored procedure is the one below.
Comments are appreciated!!
I forgot to assign a value to @totalrecords, that let's know how many records are returned by the query, for the pagination.
I have found only one way to assign the right value to @totalrecords, i executed again the query but without orderby, getting only Count(*) in the select and assigning it to @totalrecords.
I have 120.000 products with wide description and now i wait more or less 20 seconds in Admin area to load products, and avoid the timeout.
here is the stored :
USE [NopCommerce_1_8_0]
GO
/****** Object: StoredProcedure [dbo].[Nop_ProductLoadAllPaged] Script Date: 10/18/2010 11:00:09 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[Nop_ProductLoadAllPaged]
(
@CategoryID int = 0,
@ManufacturerID int = 0,
@ProductTagID int = 0,
@FeaturedProducts bit = null, --0 featured only , 1 not featured only, null - load all products
@PriceMin money = null,
@PriceMax money = null,
@RelatedToProductID int = 0,
@Keywords nvarchar(MAX),
@SearchDescriptions bit = 0,
@ShowHidden bit = 0,
@PageIndex int = 0,
@PageSize int = 2147483644,
@FilteredSpecs nvarchar(300) = null, --filter by attributes (comma-separated list). e.g. 14,15,16
@LanguageID int = 0,
@OrderBy int = 0, --0 position, 5 - Name, 10 - Price, 15 - creation date
@TotalRecords int = null OUTPUT
)
AS
BEGIN
declare @sql nvarchar(4000)
declare @orderbysql nvarchar(500)
--init
SET @Keywords = isnull(@Keywords, '')
SET @Keywords = '%' + rtrim(ltrim(@Keywords)) + '%'
SET @PriceMin = isnull(@PriceMin, 0)
SET @PriceMax = isnull(@PriceMax, 2147483644)
--filter by attributes
SET @FilteredSpecs = isnull(@FilteredSpecs, '')
CREATE TABLE #FilteredSpecs
(
SpecificationAttributeOptionID int not null
)
INSERT INTO #FilteredSpecs (SpecificationAttributeOptionID)
SELECT CAST(data as int) FROM dbo.[NOP_splitstring_to_table](@FilteredSpecs, ',');
DECLARE @SpecAttributesCount int
SELECT @SpecAttributesCount = COUNT(1) FROM #FilteredSpecs
--paging
DECLARE @PageLowerBound int
DECLARE @PageUpperBound int
DECLARE @RowsToReturn int
SET @RowsToReturn = @PageSize * (@PageIndex + 1)
SET @PageLowerBound = @PageSize * @PageIndex
SET @PageUpperBound = @PageLowerBound + @PageSize;
set @orderbysql = 'ORDER BY'
set @orderbysql =
CASE when @OrderBy = 0 AND @CategoryID IS NOT NULL AND @CategoryID > 0
THEN @orderbysql + ' pcm.DisplayOrder ASC,' else @orderbysql end
select @orderbysql =
CASE WHEN @OrderBy = 0 AND @ManufacturerID IS NOT NULL AND @ManufacturerID > 0
THEN @orderbysql + ' pmm.DisplayOrder ASC,' else @orderbysql END
select @orderbysql =
CASE WHEN @OrderBy = 0 AND @RelatedToProductID IS NOT NULL AND @RelatedToProductID > 0
THEN @orderbysql + ' rp.DisplayOrder asc,' else @orderbysql END
select @orderbysql =
CASE WHEN @OrderBy = 0
THEN @orderbysql + ' isnull(p.name,pl.name) asc,'
else @orderbysql end
select @orderbysql =
CASE WHEN @OrderBy = 5
THEN @orderbysql + ' isnull(p.name,pl.name) asc,' else @orderbysql END
select @orderbysql =
CASE WHEN @OrderBy = 10
THEN @orderbysql + ' pv.Price asc,' else @orderbysql END
select @orderbysql =
CASE WHEN @OrderBy = 15
THEN @orderbysql + ' p.CreatedOn desc,' else @orderbysql END
select @orderbysql = LEFT(@orderbysql,LEN(@orderbysql)-1)
set @sql =
'SELECT * FROM Nop_Product nopp inner join
(SELECT ROW_NUMBER() OVER
(' + @orderbysql +
') as ROWNUMBER,
p.ProductId,
isnull(p.Name,pl.name) as pname,
p.ShortDescription,
p.FullDescription,
p.AdminComment,
p.TemplateId,
p.ShowOnHomePage,
p.MetaKeywords,
p.MetaDescription,
p.MetaTitle,
p.SEName,
p.AllowCustomerReviews,
p.AllowCustomerRatings,
p.RatingSum,
p.TotalRatingVotes,
p.Published,
p.Deleted,
p.CreatedOn,
p.UpdatedOn
FROM Nop_Product p with (NOLOCK)
LEFT OUTER JOIN Nop_Product_Category_Mapping pcm with (NOLOCK) ON p.ProductID=pcm.ProductID
LEFT OUTER JOIN Nop_Product_Manufacturer_Mapping pmm with (NOLOCK) ON p.ProductID=pmm.ProductID
LEFT OUTER JOIN Nop_ProductTag_Product_Mapping ptpm with (NOLOCK) ON p.ProductID=ptpm.ProductID
LEFT OUTER JOIN Nop_RelatedProduct rp with (NOLOCK) ON p.ProductID=rp.ProductID2
LEFT OUTER JOIN Nop_ProductVariant pv with (NOLOCK) ON p.ProductID = pv.ProductID
LEFT OUTER JOIN Nop_ProductVariantLocalized pvl with (NOLOCK) ON pv.ProductVariantID = pvl.ProductVariantID AND pvl.LanguageID = ' + convert(nvarchar,@LanguageID) + '
LEFT OUTER JOIN Nop_ProductLocalized pl with (NOLOCK) ON p.ProductID = pl.ProductID AND pl.LanguageID = ' + convert(nvarchar,@LanguageID) + '
WHERE
(
(
' + convert(nvarchar,@ShowHidden) + '= 1 OR p.Published = 1
)
AND
(
p.Deleted=0
)
AND
(
' + convert(nvarchar,@ShowHidden) + '= 1 OR pv.Published = 1
)
AND
(
' + convert(nvarchar,@ShowHidden) + '= 1 OR pv.Deleted = 0
)
AND (
' + convert(nvarchar,@CategoryID) + 'IS NULL OR ' +convert(nvarchar,@CategoryID) + '=0
OR (pcm.CategoryID=' +convert(nvarchar,@CategoryID) + ' AND (' +convert(nvarchar,isnull(@FeaturedProducts,0)) + ' IS NULL OR pcm.IsFeaturedProduct=' +convert(nvarchar,isnull(@FeaturedProducts,0)) + '))
)
AND (
' +convert(nvarchar,@ManufacturerID) + ' IS NULL OR ' +convert(nvarchar,@ManufacturerID) + ' =0
OR (pmm.ManufacturerID=' +convert(nvarchar,@ManufacturerID) + ' AND (' +convert(nvarchar,isnull(@FeaturedProducts,0)) + ' IS NULL OR pmm.IsFeaturedProduct=' +convert(nvarchar,isnull(@FeaturedProducts,0)) + '))
)
AND (
' +convert(nvarchar,@ProductTagID) + ' IS NULL OR ' +convert(nvarchar,@ProductTagID) + '=0
OR ptpm.ProductTagID=' +convert(nvarchar,@ProductTagID) + '
)
AND (
' +convert(nvarchar,@RelatedToProductID) + ' IS NULL OR ' +convert(nvarchar,@RelatedToProductID) + '=0
OR rp.ProductID1=' +convert(nvarchar,@RelatedToProductID) + '
)
AND (
pv.Price BETWEEN ' +convert(nvarchar,@PriceMin) + ' AND ' +convert(nvarchar,@PriceMax) + '
)
AND (
-- search standard content
patindex(''' +convert(nvarchar,@Keywords) + ''', isnull(p.name, '''')) > 0
or patindex(''' +convert(nvarchar,@Keywords) + ''', isnull(pv.name, '''')) > 0
or patindex(''' +convert(nvarchar,@Keywords) + ''', isnull(pv.sku , '''')) > 0
or (' +convert(nvarchar,@SearchDescriptions) + ' = 1 and patindex(''' +convert(nvarchar,@Keywords) + ''', isnull(p.ShortDescription, '''')) > 0)
or (' +convert(nvarchar,@SearchDescriptions) + ' = 1 and patindex(''' +convert(nvarchar,@Keywords) + ''', isnull(p.FullDescription, '''')) > 0)
or (' +convert(nvarchar,@SearchDescriptions) + ' = 1 and patindex(''' +convert(nvarchar,@Keywords) + ''', isnull(pv.Description, '''')) > 0)
-- search language content
or patindex(''' +convert(nvarchar,@Keywords) + ''', isnull(pl.name, '''')) > 0
or patindex(''' +convert(nvarchar,@Keywords) + ''', isnull(pvl.name, '''')) > 0
or (' +convert(nvarchar,@SearchDescriptions) + ' = 1 and patindex(''' +convert(nvarchar,@Keywords) + ''', isnull(pl.ShortDescription, '''')) > 0)
or (' +convert(nvarchar,@SearchDescriptions) + ' = 1 and patindex(''' +convert(nvarchar,@Keywords) + ''', isnull(pl.FullDescription, '''')) > 0)
or (' +convert(nvarchar,@SearchDescriptions) + ' = 1 and patindex(''' +convert(nvarchar,@Keywords) + ''', isnull(pvl.Description, '''')) > 0)
)
AND
(
' +convert(nvarchar,@ShowHidden) + ' = 1
OR
(getutcdate() between isnull(pv.AvailableStartDateTime, ''1/1/1900'') and isnull(pv.AvailableEndDateTime, ''1/1/2999''))
)
AND
(
--filter by specs
' +convert(nvarchar,@SpecAttributesCount) + ' = 0
OR
(
NOT EXISTS(
SELECT 1
FROM #FilteredSpecs [fs]
WHERE [fs].SpecificationAttributeOptionID NOT IN (
SELECT psam.SpecificationAttributeOptionID
FROM dbo.Nop_Product_SpecificationAttribute_Mapping psam
WHERE psam.AllowFiltering = 1 AND psam.ProductID = p.ProductID
)
)
)
)
)
) res on res.ProductId = nopp.ProductId
and res.ROWNUMBER >= ' +convert(nvarchar,@PageLowerBound) + '
AND ROWNUMBER <= ' +convert(nvarchar,@PageUpperBound) + ''
SELECT @TotalRecords = COUNT(*)
FROM Nop_Product p with (NOLOCK)
LEFT OUTER JOIN Nop_Product_Category_Mapping pcm with (NOLOCK) ON p.ProductID=pcm.ProductID
LEFT OUTER JOIN Nop_Product_Manufacturer_Mapping pmm with (NOLOCK) ON p.ProductID=pmm.ProductID
LEFT OUTER JOIN Nop_ProductTag_Product_Mapping ptpm with (NOLOCK) ON p.ProductID=ptpm.ProductID
LEFT OUTER JOIN Nop_ProductVariant pv with (NOLOCK) ON p.ProductID = pv.ProductID
LEFT OUTER JOIN Nop_ProductVariantLocalized pvl with (NOLOCK) ON pv.ProductVariantID = pvl.ProductVariantID AND pvl.LanguageID = @LanguageID
LEFT OUTER JOIN Nop_ProductLocalized pl with (NOLOCK) ON p.ProductID = pl.ProductID AND pl.LanguageID = @LanguageID
WHERE
(
(
@ShowHidden = 1 OR p.Published = 1
)
AND
(
@ShowHidden = 1 OR pv.Published = 1
)
AND
(
p.Deleted=0
)
AND (
@CategoryID IS NULL OR @CategoryID=0
OR (pcm.CategoryID=@CategoryID AND (@FeaturedProducts IS NULL OR pcm.IsFeaturedProduct=@FeaturedProducts))
)
AND (
@ManufacturerID IS NULL OR @ManufacturerID=0
OR (pmm.ManufacturerID=@ManufacturerID AND (@FeaturedProducts IS NULL OR pmm.IsFeaturedProduct=@FeaturedProducts))
)
AND (
@ProductTagID IS NULL OR @ProductTagID=0
OR ptpm.ProductTagID=@ProductTagID
)
AND (
pv.Price BETWEEN @PriceMin AND @PriceMax
)
AND (
-- search standard content
patindex(@Keywords, isnull(p.name, '')) > 0
or patindex(@Keywords, isnull(pv.name, '')) > 0
or patindex(@Keywords, isnull(pv.sku , '')) > 0
or (@SearchDescriptions = 1 and patindex(@Keywords, isnull(p.ShortDescription, '')) > 0)
or (@SearchDescriptions = 1 and patindex(@Keywords, isnull(p.FullDescription, '')) > 0)
or (@SearchDescriptions = 1 and patindex(@Keywords, isnull(pv.Description, '')) > 0)
-- search language content
or patindex(@Keywords, isnull(pl.name, '')) > 0
or patindex(@Keywords, isnull(pvl.name, '')) > 0
or (@SearchDescriptions = 1 and patindex(@Keywords, isnull(pl.ShortDescription, '')) > 0)
or (@SearchDescriptions = 1 and patindex(@Keywords, isnull(pl.FullDescription, '')) > 0)
or (@SearchDescriptions = 1 and patindex(@Keywords, isnull(pvl.Description, '')) > 0)
)
AND
(
@ShowHidden = 1
OR
(getutcdate() between isnull(pv.AvailableStartDateTime, '1/1/1900') and isnull(pv.AvailableEndDateTime, '1/1/2999'))
)
AND
(
--filter by specs
@SpecAttributesCount = 0
OR
(
NOT EXISTS(
SELECT 1
FROM #FilteredSpecs [fs]
WHERE [fs].SpecificationAttributeOptionID NOT IN (
SELECT psam.SpecificationAttributeOptionID
FROM dbo.Nop_Product_SpecificationAttribute_Mapping psam
WHERE psam.AllowFiltering = 1 AND psam.ProductID = p.ProductID
)
)
)
)
)
execute sp_executesql @sql
SET ROWCOUNT 0
DROP TABLE #FilteredSpecs
END