C# 使用自定义分页优化搜索SQL
使用asp.net mvc应用程序和c#。我们正在做一个搜索页面 更新了我的答案。请参见下面我自己的答案并提出建议C# 使用自定义分页优化搜索SQL,c#,asp.net,sql,sql-server,sql-server-2008,C#,Asp.net,Sql,Sql Server,Sql Server 2008,使用asp.net mvc应用程序和c#。我们正在做一个搜索页面 更新了我的答案。请参见下面我自己的答案并提出建议 不幸的是,select into在sql azure中不起作用 帮帮我 我有下表来显示我的项目搜索结果 项目表 ITEMID、SHOPID、ITEMNAME、描述、价格、CATID 工作台 SHOPId,标题,城市ID,活动 城市表 CITYID、CITYName、REGIONID、CountryISO 类别表 CATID,CATNAME 这是我的搜索查询,它给出给
不幸的是,select into在sql azure中不起作用 帮帮我 我有下表来显示我的项目搜索结果 项目表
- ITEMID、SHOPID、ITEMNAME、描述、价格、CATID
- SHOPId,标题,城市ID,活动
- CITYID、CITYName、REGIONID、CountryISO
- CATID,CATNAME
DECLARE @unitItems INT=20
DECLARE @sortOrder INT=0
DECLARE @catId INT
DECLARE @search NVARCHAR (100)=''
DECLARE @REGIONID INT=0
DECLARE @cityId INT=0
DECLARE @maxPrice DECIMAL (10, 2)
DECLARE @page INT
DECLARE @currentDate DATETIME2 (0)
set @unitItems=20
set @catId=0
set @sortOrder=0
set @search=''
set @cityId=1
set @maxPrice=0
set @page=1
set @currentDate='2013-02-24 13:14:58.073'
;WITH itemresult AS (
SELECT IT.ITEMID, IT.ITEMNAME, IT.DESCRIPTION, IT.PRICE,
IT.CATID, C.CATNAME AS CATNAME,S.HEADER AS SHOPHEADER,CI.CITYNAME AS CITY,
ROW_NUMBER() OVER (ORDER BY IT.SHOWDATE DESC) AS RowNumber
FROM ITEM AS IT INNER JOIN SHOP AS S ON IT.SHOPId = S.ShopId
INNER JOIN CITY AS CI ON CI.CITYID = S.CITYID
INNER JOIN COUNTRY AS CY ON CI.COUNTRYISO = CY.COUNTRYISO
INNER JOIN REGION AS R ON CI.REGIONID = R.REGIONID
INNER JOIN CITY AS CI2 ON CI2.CITYID = @cityId
INNER JOIN CATEGORY AS C ON IT.CATID = C.CATID
WHERE S.ACTIVE = 1
GROUP BY IT.ITEMID, IT.ITEMNAME, IT.HEADER, IT.DESCRIPTION, IT.PRICE,
IT.CATID, IT.SHOWDATE,S.HEADER,C.CATNAME,CI.CITYNAME)
SELECT IT.*, CEILING(CAST(RN AS float) / @unitItems) AS UNITPAGES, RN AS UNITROWS
FROM itemresult IT
INNER JOIN (SELECT Max(RowNumber) AS RN FROM itemresult) SUBQ ON 1=1
WHERE IT.RowNumber BETWEEN (@page - 1) * @unitItems + 1
AND @unitItems * @page
问题:
现在的问题是我们正在UI中添加新的更改。搜索UI现在将显示如下内容
第一个结果集-->假设总共找到230条记录
在Fiddle中看到的搜索结果
第二个结果集-->230条记录的不同类别和计数
CatId、CatName、TotalCountInSearch
例:1本书25和2本体育43和8其他52。
显示我可以在UI中显示如下内容
- 所有类别(120)
- 书籍(25)
- 体育(43)
- 其他(52)
- 所有城市(10)
- 钦奈(4)
- 班格罗(3)
- 其他(3)
这是基于类别检索计数
select 'All categories' catname, count(*) catcount from itemtable
union all
select catname, count(catid) catcount
from itemtable inner join categorytable on categorytable.catid = itemtable.catid
group by catname
这是基于城市检索计数
select 'All cities' cityname, count(*) catcount from itemtable
union all
select cityname, count(catid) catcount
from itemtable inner join shoptable on itemtable.shopid = shoptable.shopid
inner join citytable on citytable.cityid = shoptable.cityid
group by cityname
试试这个。我希望这能满足你的期望
CREATE VIEW vSequence AS
WITH itemresult AS (
SELECT IT.ITEMID, IT.ITEMNAME, IT.DESCRIPTION, IT.PRICE,
IT.CATID, C.CATNAME AS CATNAME,S.HEADER AS SHOPHEADER,CI.CITYNAME AS CITY,CI.CITYID,
ROW_NUMBER() OVER (ORDER BY IT.SHOWDATE DESC) AS RowNumber
FROM ITEM AS IT INNER JOIN SHOP AS S ON IT.SHOPId = S.ShopId
INNER JOIN CITY AS CI ON CI.CITYID = S.CITYID
INNER JOIN COUNTRY AS CY ON CI.COUNTRYISO = CY.COUNTRYISO
INNER JOIN REGION AS R ON CI.REGIONID = R.REGIONID
INNER JOIN CITY AS CI2 ON CI2.CITYID = 1
INNER JOIN CATEGORY AS C ON IT.CATID = C.CATID
WHERE S.ACTIVE = 1
GROUP BY IT.ITEMID, IT.ITEMNAME, IT.HEADER, IT.DESCRIPTION, IT.PRICE,
IT.CATID, IT.SHOWDATE,S.HEADER,C.CATNAME,CI.CITYNAME,CI.CITYID)
SELECT * FROM itemresult IT
GO
SELECT IT.*, CEILING(CAST(RN AS float) / 20) AS UNITPAGES, RN AS UNITROWS
FROM vSequence IT
INNER JOIN (SELECT Max(RowNumber) AS RN FROM vSequence) SUBQ ON 1=1
WHERE IT.RowNumber BETWEEN (1 - 1) * 20 + 1
AND 20 * 1
GO
SELECT IT.CATID,RS.CATNAME , CONVERT(varchar(10), SUM(CASE WHEN IT.CATID = CAT.CATID THEN 1 ELSE 0 END)) AS 'Count'
FROM vSequence RS INNER JOIN ITEM IT ON RS.CATID = IT.CATID
INNER JOIN CATEGORY CAT
ON IT.CATID = CAT.CATID GROUP BY IT.CATID,RS.CATNAME
GO
SELECT CIT.CITYID,CITYNAME,CONVERT(varchar(10), SUM(CASE WHEN CIT.REGIONID = REG.REGIONID THEN 1 ELSE 0 END)) AS 'Count'
FROM COUNTRY CON INNER JOIN REGION REG
ON CON.COUNTRYISO = REG.COUNTRYISO
INNER JOIN CITY CIT ON CIT.REGIONID = REG.REGIONID
INNER JOIN vSequence RS ON CIT.CITYID=RS.CITYID GROUP BY REG.REGIONID,CITYNAME, CIT.CITYID
示例。我从您的评论中了解到,我认为您需要的是通过执行单个存储过程来获得
3个结果集。您还想知道查询是否得到优化
我认为您的vSequence视图
现在还不错(因此,我不会在这里添加我的答案)。您需要的是创建一个存储过程
,以使用视图获得三个不同的结果集,如下所示。我将您在fiddle中声明的变量列表作为存储过程的参数。我在每个变量旁边都做了注释。由于您的过滤要求不明确,我将其保留为现有的
CREATE PROCEDURE myStoredProcedure
@unitItems INT=20, --number of items per page
@sortOrder INT=0, --not used
@catId INT, --not in use
@search NVARCHAR (100)='', --not used
@REGIONID INT=0, -- not used
@cityId INT=0, -- not used
@maxPrice DECIMAL (10, 2), -- not used
@page INT, --page number
@currentDate DATETIME2 (0) -- not used
AS
BEGIN
/*
Query 1
Note: I have assumed your @page start at 1 and also changed the where clause
to bring correct data based on @page & @unitItems parameters
*/
SELECT IT.*, CEILING(CAST(RN AS float) / 20) AS UNITPAGES, RN AS UNITROWS
FROM vSequence IT INNER JOIN (SELECT Max(RowNumber) AS RN FROM vSequence) SUBQ ON 1=1
WHERE IT.RowNumber BETWEEN (@unitItems * (@page - 1) + 1) AND @unitItems
/* Query 2 */
SELECT IT.CATID,RS.CATNAME , CONVERT(varchar(10),
SUM(CASE WHEN IT.CATID = CAT.CATID THEN 1 ELSE 0 END)) AS 'Count'
FROM vSequence RS
INNER JOIN ITEM IT ON RS.CATID = IT.CATID
INNER JOIN CATEGORY CAT ON IT.CATID = CAT.CATID
GROUP BY IT.CATID,RS.CATNAME
/* Query 3 */
SELECT CIT.CITYID,CITYNAME,CONVERT(varchar(10),
SUM(CASE WHEN CIT.REGIONID = REG.REGIONID THEN 1 ELSE 0 END)) AS 'Count'
FROM COUNTRY CON
INNER JOIN REGION REG ON CON.COUNTRYISO = REG.COUNTRYISO
INNER JOIN CITY CIT ON CIT.REGIONID = REG.REGIONID
INNER JOIN vSequence RS ON CIT.CITYID=RS.CITYID
GROUP BY REG.REGIONID,CITYNAME, CIT.CITYID
END
以下是如何在Management Studio
中执行存储过程(请为参数使用适当的值):
要在C
代码中执行此存储过程,请使用带有DataAdapter
的参数化查询,如下所示:
DataSet ds = new DataSet();
using (SqlConnection connection = new SqlConnection("your-Connection-String-here"))
{
SqlDataAdapter adapter = new SqlDataAdapter();
adapter.SelectCommand = new SqlCommand("myStoredProcedure", connection);
adapter.SelectCommand.CommandType = CommandType.StoredProcedure;
adapter.SelectCommand.Parameters.AddWithValue("@unitItems",20);
//add other parameters as above here
adapter.SelectCommand.Parameters.AddWithValue("@page",1); //correct page number
adapter.Fill(ds);
}
//Now you can access all query results as
ds.Tables[0]; //results from query1
ds.Tables[1]; //results from query2
ds.Tables[2]; //results from query3
最后,我创建了下面的SP并解决了问题
请告诉我这是正确的方法吗?
我使用了临时表、分组集、分组ID
你可以在这里看到代码
创建过程[dbo]。[Item\u SearchItems\u New]
(
@购物中心
,@unitItems INT=20
,@sortOrder INT=0
,@language CHAR(2)=“EN”
,@catId INT
,@search-NVARCHAR(100)=”
,@countryIso NCHAR(2)=”
,@regionNr INT=0
,@cityId INT=0
,@maxPrice十进制(10,2)
,@page INT
,@currentDate日期时间2(0)
,@距离数字(4,1)
,@isFavoriteShop位=0
,@currentUserNr INT=0
,@纬度浮动(53)=0
,@经度浮动(53)=0
,@itemType TINYINT=0
,@unitRows INT输出
,@unitPages INT输出
)
作为
开始
将XACT_中止设置为ON
不计较
声明@sql NVARCHAR(最大值)
,@sqlSelect-NVARCHAR(最大值)=”
,@sqltentable NVARCHAR(MAX)='#itemSearch'
,@sqlcounttentable NVARCHAR(MAX)='#itemCount'
,@sqlInto NVARCHAR(最大值)=”
,@sqlFrom NVARCHAR(MAX)=”
,@sqlClause NVARCHAR(MAX)=”
,@sqlGroup NVARCHAR(最大值)=”
,@params NVARCHAR(最大值)
,@citySearch位=0
,@gpsSearch位=0
,@sortOrderString NVARCHAR(MAX)='ORDER BY IT.CREATEDATE DESC'
,@sortOrderString2 NVARCHAR(最大值)=”
如果(@cityid 0)和(@latitude=0)
选择@cityid=cityid
来自用户信息
其中USERNR=@currentUserNr
ELSE IF(@cityid 0)
设置@gpsSearch=1
ELSE IF(@cityid>0)
设置@citySearch=1
IF(@sortOrderString2='')
设置@sortOrderString2=@sortOrderString
如果(@unitItems=0)
设置@unitItems=20
如果(@page 0)
SET@sqlClause=@sqlClause+
'和(C.CATID=@CATID或C.PARENTCATID=@CATID)'
如果(@ShopNr>0)
SET@sqlClause=@sqlClause+
'IT.ShopNR=@ShopNR'
如果(@搜索“”)
SET@sqlClause=@sqlClause+
'和((类似于'%'+@search+'%''的IT.HEADER)或(类似于'%'+@search+'%''的IT.DESCRIPTION))'
将@sqlInto='设置为'+@sqltentable+'';
SET@sql=@sqlSelect+
@sqlInto+
@sqlFrom+
@SQL子句+
@sqlGroup
设置@sql=@sql+';
选择@unitRows=@@ROWCOUNT
,@unitPages=(@unitRows/@unitItems)+1;
挑选*
从“++@sqltentable+”开始
其中(@page-1)*@unitItems+1和@unitItems*@page之间的行号
“+@sortOrderString2+”;
选择CATNAME
城市
,计数(*)为ITEMCOUNT
,将_ID(CATNAME,CITY)分组为ITEMCOUNTTYPEID
进入“++@sqlcountetreable+”
来自“++@sqltentable+”
按分组集分组
(
DataSet ds = new DataSet();
using (SqlConnection connection = new SqlConnection("your-Connection-String-here"))
{
SqlDataAdapter adapter = new SqlDataAdapter();
adapter.SelectCommand = new SqlCommand("myStoredProcedure", connection);
adapter.SelectCommand.CommandType = CommandType.StoredProcedure;
adapter.SelectCommand.Parameters.AddWithValue("@unitItems",20);
//add other parameters as above here
adapter.SelectCommand.Parameters.AddWithValue("@page",1); //correct page number
adapter.Fill(ds);
}
//Now you can access all query results as
ds.Tables[0]; //results from query1
ds.Tables[1]; //results from query2
ds.Tables[2]; //results from query3
CREATE PROCEDURE [dbo].[Item_SearchItems_New]
(
@ShopNr INT
,@unitItems INT = 20
,@sortOrder INT = 0
,@language CHAR(2) = 'EN'
,@catId INT
,@search NVARCHAR(100) = ''
,@countryIso NCHAR(2) = ''
,@regionNr INT = 0
,@cityId INT = 0
,@maxPrice DECIMAL(10, 2)
,@page INT
,@currentDate DATETIME2(0)
,@distance NUMERIC(4, 1)
,@isFavoriteShop BIT = 0
,@currentUserNr INT = 0
,@latitude FLOAT(53) = 0
,@longitude FLOAT(53) = 0
,@itemType TINYINT = 0
,@unitRows INT OUTPUT
,@unitPages INT OUTPUT
)
AS
BEGIN
SET XACT_ABORT ON
SET NOCOUNT ON
DECLARE @sql NVARCHAR(MAX)
,@sqlSelect NVARCHAR(MAX) = ''
,@sqlTempTable NVARCHAR(MAX) = '#itemSearch'
,@sqlCountTempTable NVARCHAR(MAX) = '#itemCount'
,@sqlInto NVARCHAR(MAX) = ''
,@sqlFrom NVARCHAR(MAX) = ''
,@sqlClause NVARCHAR(MAX) = ''
,@sqlGroup NVARCHAR(MAX) = ''
,@params NVARCHAR(MAX)
,@citySearch bit = 0
,@gpsSearch bit = 0
,@sortOrderString NVARCHAR(MAX) = 'ORDER BY IT.CREATEDATE DESC'
,@sortOrderString2 NVARCHAR(MAX) = ''
IF (@cityid <= 0) AND (@currentUserNr > 0) AND (@latitude = 0)
SELECT @cityid = CITYID
FROM USERINFO
WHERE USERNR = @currentUserNr
ELSE IF (@cityid <= 0) AND (@latitude > 0)
SET @gpsSearch = 1
ELSE IF (@cityid > 0)
SET @citySearch = 1
IF (@sortOrderString2 = '')
SET @sortOrderString2 = @sortOrderString
IF (@unitItems = 0)
SET @unitItems = 20
IF (@page <= 0)
SET @page = 1
SET @sqlSelect =
'SELECT J.URLNAME
,IT.ITEMNR
,IT.USERNR
,IT.ShopNR
,IT.ITEMID
,IT.ITEMNAME
,IT.HEADER
,IT.DESCRIPTION
,IT.PRICE
,IT.CREATEDATE
,IT.ITEMSTATUS
,IT.CURRENCYCODE
,IT.CATID
,IT.VISIT
,IT.ENDDATE
,IT.PREAMBLE
,IT.SHOWDATE
,IT.LASTUPDATED
,C.CATNAME AS CATNAME
,J.HEADER AS ShopHEADER
,J.LATITUDE
,J.LONGITUDE
,R.REGIONNAME AS REGIONNAME
,CY.COUNTRYISO
,R.REGIONNR
,CY.COUNTRYNAME AS COUNTRYNAME
,CI.CITYNAME AS CITY
,ROW_NUMBER() OVER (' + @sortOrderString + ') AS RowNumber'
SET @sqlGroup =
' GROUP BY J.URLNAME
,IT.ITEMNR
,IT.USERNR
,IT.ShopNR
,IT.ITEMID
,IT.ITEMNAME
,IT.HEADER
,IT.DESCRIPTION
,IT.PRICE
,IT.CREATEDATE
,IT.ITEMSTATUS
,IT.CURRENCYCODE
,IT.CATID
,IT.VISIT
,IT.ENDDATE
,IT.PREAMBLE
,IT.SHOWDATE
,IT.LASTUPDATED
,C.CATNAME
,J.HEADER
,J.LATITUDE
,J.LONGITUDE
,R.REGIONNAME
,CY.COUNTRYISO
,R.REGIONNR
,CY.COUNTRYNAME
,CI.CITYNAME'
SET @sqlFrom =
' FROM dbo.ITEM AS IT
INNER JOIN dbo.Shop AS J
ON IT.ShopNR = J.ShopNR
INNER JOIN dbo.CITY AS CI
ON CI.CITYID = J.CITYID
INNER JOIN dbo.COUNTRY AS CY
ON CI.COUNTRYISO = CY.COUNTRYISO
INNER JOIN dbo.REGION AS R
ON CI.REGIONNR = R.REGIONNR'
SET @sqlFrom = @sqlFrom +
' INNER JOIN dbo.CATEGORY AS C
ON IT.CATID = C.CATID '
SET @sqlClause =
' WHERE J.ACTIVE = 1
AND IT.ITEMSTATUS = 1
AND IT.ENDDATE > @currentDate'
IF (@itemType = 1)
SET @sqlClause = @sqlClause +
' AND IT.ITEMTYPE = 1'
IF (@catId > 0)
SET @sqlClause = @sqlClause +
' AND (C.CATID = @catId OR C.PARENTCATID = @catId)'
IF (@ShopNr > 0)
SET @sqlClause = @sqlClause +
' AND IT.ShopNR = @ShopNr'
IF (@search <> '')
SET @sqlClause = @sqlClause +
' AND ((IT.HEADER LIKE ''%' + @search + '%'') OR (IT.DESCRIPTION LIKE ''%' + @search + '%''))'
SET @sqlInto = ' INTO ' + @sqlTempTable + ' ';
SET @sql = @sqlSelect +
@sqlInto +
@sqlFrom +
@sqlClause +
@sqlGroup
SET @sql = @sql + ';
SELECT @unitRows = @@ROWCOUNT
,@unitPages = (@unitRows / @unitItems) + 1;
SELECT *
FROM ' + @sqlTempTable + ' AS IT
WHERE RowNumber BETWEEN (@page - 1) * @unitItems + 1 AND @unitItems * @page
' + @sortOrderString2 + ';
SELECT CATNAME
,CITY
,COUNT(*) AS ITEMCOUNT
,GROUPING_ID(CATNAME, CITY) AS ITEMCOUNTTYPEID
INTO '+ @sqlCountTempTable + '
FROM ' + @sqlTempTable + '
GROUP BY GROUPING SETS
(
(CATNAME)
,(CITY)
,()
)
SELECT ISNULL(CATNAME, ''All Categories'') AS CATNAME
,ITEMCOUNT
FROM '+ @sqlCountTempTable + '
WHERE ITEMCOUNTTYPEID IN (1, 3)
ORDER BY ITEMCOUNTTYPEID DESC
,CATNAME
SELECT ISNULL(CITY, ''All Cities'') AS CITY
,ITEMCOUNT
FROM '+ @sqlCountTempTable + '
WHERE ITEMCOUNTTYPEID IN (2, 3)
ORDER BY ITEMCOUNTTYPEID DESC
,CITY';
SELECT @params =
N'@language nchar(2), ' +
N'@ShopNr int, ' +
N'@cityId int, ' +
N'@catId int, ' +
N'@distance numeric(4,1), ' +
N'@currentDate datetime, ' +
N'@unitItems int,' +
N'@countryIso nchar(2),' +
N'@regionNr int,' +
N'@page int,' +
N'@currentUserNr int,' +
N'@latitude float,' +
N'@longitude float,' +
N'@unitRows int OUTPUT,' +
N'@unitPages int OUTPUT'
--print @sql
EXEC sp_executesql @sql
,@params
,@language
,@ShopNr
,@cityId
,@catId
,@distance
,@currentDate
,@unitItems
,@countryIso
,@regionNr
,@page
,@currentUserNr
,@latitude
,@longitude
,@unitRows OUTPUT
,@unitPages OUTPUT
END
GO
DECLARE @unitPages INT
,@unitRows INT
exec Item_SearchItems_New @ShopNr=0,@unitItems=20,@catId=0,@language='',@sortOrder=0,@search=default,@countryIso='in',
@regionNr=2702259,@cityId=2702261,@maxPrice=0,@page=1,@distance=50,@currentDate='2013-02-24 19:29:50.623',@isFavoriteShop=0,
@currentUserNr=0,@latitude=0,@longitude=0,@itemType=0,@unitRows = @unitRows OUTPUT, @unitPages = @unitPages OUTPUT
SELECT @unitPages, @unitRows