Разбиение на родительский элемент в SQL Server по запросу родительский / дочерний - PullRequest
0 голосов
/ 24 мая 2018

(SQL Server 2012 - Web Edition)

У меня есть отношение родитель / потомок (один ко многим) в запросе, например:

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

Вопрос, который у меня возникает, заключается в том, можно ли разбить на страницы родительскую таблицу (а) вместо всего запроса?Могу ли я изменить свой запрос на разбиение на страницы (не sql, который извлекает сам запрос), чтобы при запросе 10 строк он выдавал мне 10 строк от родителя с числом дочерних элементов 'x'?

Iзнаю, что я не даю здесь более полную картину, но более масштабная картина выглядит ужасно.Если нужно, мы можем пойти туда, но это там.Вот небольшой вкус того, куда мы идем с этим:

    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

Ответы [ 2 ]

0 голосов
/ 24 мая 2018

Вы можете добавить

,DENSE_RANK() OVER (ORDER BY table_a.primary_key)

Это косвенно даст тот же результат, что и

,ROW_NUMBER() OVER(ORDER BY table_a.primary_key) 

, но первый будет в конечном наборе результатов, вместо этого возвращаясь к таблице a дляпоследний фрагмент кода.

Но учтите недостаток: любая дополнительная функция ранжирования вызовет дополнительную операцию сортировки для набора результатов!Это может существенно повлиять на производительность запроса.Если дело обстоит именно так в вашем сценарии, я бы порекомендовал следовать решению Tab Allemans и использовать cte.

0 голосов
/ 24 мая 2018

Вы можете выполнить нумерацию страниц в CTE, который получает только родительские строки, а затем объединить дочерние строки в последующем CTE или в основном запросе.

Из-за динамического способа использования этого,это может потребовать построения вашего запроса разбивки на страницы из тех же строительных блоков, которые вы используете для построения @query.Не видя код, который создает @query, я не могу быть более конкретным, чем этот.

...