(SQL Server 2012 - 网络版)
我在查询中有一个父/子(一对多)关系:
SELECT a.a, a.b, b.c
FROM tablea INNER JOIN
tableb ON b.pk = a.fk
我有一个巨大的分页查询,包含使用标准(伪代码):
WITH C as (SELECT top(@perpage*@pagenum) rowID = row_number() OVER (somefield)),
SELECT c.* FROM C (query) WHERE DT_RowId > (@pagenum-1)*@perpage
我遇到的问题是在这种情况下是否可以对父表(a)进行分页,而不是整个查询?我可以修改我的分页查询(而不是自己提取查询的sql),这样当我要求10行时,它会从父项中获取10行,并附加“x”个子项吗?
我知道我不是在这里提供更大的图片,但更大的图片是丑陋的。如果需要,我们可以去那里,但它就在那里。这是我们对此的一个小尝试:
IF UPPER(LEFT(@rSQL, 6)) = 'SELECT'
BEGIN
SET @rSQL = 'SELECT * FROM (' + @rSQL + ')' + ' as rTBL';
SET @rSQL = RIGHT(@rSQL, LEN(@rSQL)-7);
IF (LEN(LTRIM(@search)) > 0)
BEGIN
SET @rPaging =
'IF (@schemaonly=1) SET FMTONLY ON;
SELECT @ttlrows = COUNT(*) FROM (SELECT ' + @rSQL + @rWhere + ') AS TBL;
WITH C as (select top(@perpage*@pagenum) DT_RowId = ROW_NUMBER() OVER (' + @rOrder + '), ';
SET @rPaging = @rPaging + @rSQL + @rWhere + ')
SELECT C.*' + @rcols + ', (@perpage-1) * @pagenum as pagenum, @ttlrows as ct, CEILING(@ttlrows / CAST(@perpage AS FLOAT)) as pages
FROM C '+ @query + ' WHERE DT_RowId > (@pagenum-1) * @perpage ';
END
ELSE
BEGIN
SET @rPaging =
'IF (@schemaonly=1) SET FMTONLY ON;
SELECT @ttlrows = COUNT(*) FROM (' + @oSQL + ') AS SUBQUERY;
WITH C as (select top(@perpage*@pagenum) DT_RowId = ROW_NUMBER() OVER (' + @rOrder + '), ';
SET @rPaging = @rPaging + @rSQL + ')
SELECT C.*' + @rcols + ',(@perpage-1) * @pagenum as pagenum, @ttlrows as ct, CEILING(@ttlrows / CAST(@perpage AS FLOAT)) as pages
FROM C '+ @query + ' WHERE DT_RowId > (@pagenum-1) * @perpage ';
END
PRINT @rPaging;
EXECUTE SP_EXECUTESQL @rPaging, @parms, @ttlrows out, @schemaonly, @perpage, @pagenum, @fksiteID, @filter1, @filter2, @filter3, @filter4, @intfilter1, @intfilter2, @intfilter3, @intfilter4, @datefilter1, @datefilter2, @search;
SET FMTONLY OFF;
END
ELSE
BEGIN
SET @rSQL = LTRIM(REPLACE(UPPER(@rSQL), 'EXEC',''));
EXECUTE SP_EXECUTESQL @rSQL, @parms, @ttlrows out, @schemaonly, @perpage, @pagenum, @fksiteID, @filter1, @filter2, @filter3, @filter4, @intfilter1, @intfilter2, @intfilter3, @intfilter4, @datefilter1, @datefilter2;
END
答案 0 :(得分:3)
您可以在仅获取父行的CTE中进行分页,然后在后续CTE或主查询中连接子行。
由于您使用此动态方式,这可能需要从您用于构建@query
的相同构建块构建分页查询。如果没有看到构建@query
的代码,我就不能比这更具体了。
答案 1 :(得分:3)
你可以添加
,DENSE_RANK() OVER (ORDER BY table_a.primary_key)
这将间接提供与
相同的结果,ROW_NUMBER() OVER(ORDER BY table_a.primary_key)
但是前者将在最终结果集上,而不是返回到表a中的后一个代码片段。
但请注意缺点:任何额外的排名功能都会对结果集强制执行额外的排序操作!这可能会显着影响查询性能。如果您的方案中出现这种情况,我建议您遵循Tab Allemans解决方案并使用cte。