如何通过分页将动态过滤器传递到存储过程

时间:2010-07-12 04:45:18

标签: sql-server

我有一个存储过程,可以获取项目列表,排序并应用分页 但是我还需要添加过滤功能。所以我想做的是传递一串过滤器  比如“27 ='某些公司'; 32 ='奥克兰'”,并将其拆分为临时表(见下面的拆分代码)

建议拆分代码

 CREATE TABLE #Filters 
    (       
        ModelEntityId int not null, 
        ValueText nvarchar(max)
    ) 

    WHILE (@pos <> 0)
    BEGIN
        SET @NextFilter = substring(@Filters,1,@Pos - 1)
        SET @SubPos = charindex('=',@NextFilter)

        insert into #Filters (ModelEntityId, ValueText) 
                Values (substring(@NextFilter, 1, @SubPos-1),
                        substring(@NextFilter,@subPos+1, len(@NextFilter))) 

        SET @Filters = substring(@Filters,@pos+1,len(@Filters))
        SET @pos = charindex('~',@Filters)
    END

我的数据以非常通用的方式存储,因此一个“记录”可能看起来像这样

ContainerModelEntityId DataContainerId ModelEntityId ValueText
4                      17              5             'sunshine company'
4                      17              6             '12999'
4                      17              7             '01/12/2010'
...
4                      18              5             'moonlight company...  
  • ContainerModelEntityId是容器类型(即业务,人员等)
  • DataContainerId是'row'
  • ModelEntityId是'field'
  • ValueText是实际值

目前sp下面有一个传入它的SortFieldId,并且假设是5,然后我在我的数据表上进行连接并对ModelEntityId = 5进行排序。但是现在我还想做一个加入我的#filter表中的值,只返回值匹配的结果(我在下面的代码中放置了一个注释,以显示我认为逻辑应该去的地方)。但是在这一点上我已经让我大吃一惊,因为固定的逻辑通常让我很头疼。任何帮助赞赏。

当前存储过程

   ALTER PROCEDURE [dbo].[GetSortedIndex]   
        @ContainerModelEntityId int,
        @ParentRecordId         int,
        @SortFieldId            int,
        @PageIndex              int,
        @PageSize               int,
        @Ascending              bit 
    AS
    BEGIN
        -- SET NOCOUNT ON added to prevent extra result sets from
        -- interfering with SELECT statements.
        SET NOCOUNT ON;

        CREATE TABLE #SelectedRecords 
        (       
            ContainerModelEntityId int not null, 
            DataContainerId int not null,
            DataInstanceId int not null,
            ParentDataContainerId int null 
        ) 

        DECLARE @LowerBound int, @UpperBound int

        -- Pagination   
        select @LowerBound = ((@PageIndex) * @PageSize)+1
        select @UpperBound = (@PageIndex+1) * @PageSize+1

        IF @Ascending = 1 
        BEGIN
            INSERT INTO #SelectedRecords
            SELECT ContainerModelEntityId, 
                           DataContainerId, 
                           DataInstanceId, 
                           ParentDataContainerId 
                    FROM
            ( 
                select di.ModelEntityId as 'ContainerModelEntityId',
                          dc.DataContainerId,
                          di.DataInstanceId, 
                          dv.ModelEntityId, 
                          dc.ParentDataContainerId,
                  ROW_NUMBER() OVER (ORDER BY dv.ValueText) AS row 
                from datacontainer dc
                inner join dataInstance di 
                           on dc.DataContainerId = di.DataContainerId
                        //some funky join on #Filter table to go here
                        left outer join dataValue dv 
                          on di.DataInstanceId = dv.DataInstanceId 
                          and dv.ModelEntityId=@SortFieldId
                where ISNULL(dc.ParentDataContainerId,0) 
                               = ISNULL(@ParentRecordId,0) 
                          and di.IsCurrent = 1 
                          and di.ModelEntityId = @ContainerModelEntityId
            ) tbl
                WHERE tbl.row >= @LowerBound AND
              tbl.row < @UpperBound
    END
    ELSE
    BEGIN
        INSERT INTO #SelectedRecords
        SELECT ContainerModelEntityId, DataContainerId, 
               DataInstanceId, ParentDataContainerId 
        FROM
        ( 
            select di.ModelEntityId as 'ContainerModelEntityId', 
                dc.DataContainerId, di.DataInstanceId, 
                dv.ModelEntityId, dc.ParentDataContainerId, dv.ValueText,
            ROW_NUMBER() OVER (ORDER BY dv.ValueText DESC) AS row 
        from datacontainer dc
        inner join dataInstance di 
                on dc.DataContainerId = di.DataContainerId
            //some funky join on #Filter table to go here
        left outer join dataValue dv 
                on di.DataInstanceId = dv.DataInstanceId 
                   and dv.ModelEntityId=@SortFieldId 
        where ISNULL(dc.ParentDataContainerId,0) = ISNULL(@ParentRecordId,0) 
                  and di.IsCurrent = 1 
                  and di.ModelEntityId=@ContainerModelEntityId 
        ) tbl
        WHERE tbl.row >= @LowerBound AND
              tbl.row < @UpperBound 
    END

    DECLARE @Count int
    SELECT @Count = (SELECT COUNT(*) FROM DataContainer dc
    INNER JOIN DataInstance di ON di.DataContainerId = dc.DataContainerId
    WHERE di.ModelEntityId = @ContainerModelEntityId 
     AND ISNULL(dc.ParentDataContainerId,0) = ISNULL(@ParentRecordId,0) 
     AND di.IsCurrent=1)

    SELECT ContainerModelEntityId, DataContainerId, 
           ParentDataContainerId, 
           isnull(dv.ModelEntityId, @sortFieldId) as 'ModelEntityId', 
           dv.ValueText, 
           @Count [TotalRecords] 
    FROM #SelectedRecords sr  
    left outer join dataValue dv ON sr.DataInstanceId = dv.DataInstanceId

END

1 个答案:

答案 0 :(得分:0)

好的,现在有所收获

ALTER PROCEDURE [dbo].[GetSortedIndex]  
@ContainerModelEntityId int,
@ParentRecordId         int,
@SortFieldId            int,
@PageIndex              int,
@PageSize               int,
@Ascending              bit = 1,
@Filters                varchar(max) = null 

AS 开始      - 添加SET NOCOUNT ON以防止出现额外的结果集      - 干扰SELECT语句。     设置NOCOUNT ON;

DECLARE @NextFilter NVARCHAR(100)
DECLARE @Pos INT
DECLARE @SubPos INT
DECLARE @NextPos INT

CREATE TABLE #Filters 
(       
    ModelEntityId int not null, 
    ValueText nvarchar(max)
) 

CREATE TABLE #SelectedRecords 
(   row int,    
    ContainerModelEntityId int not null, 
    DataContainerId int not null,
    DataInstanceId int not null,
    ParentDataContainerId int null 
) 

DECLARE @LowerBound int, @UpperBound int

-- Pagination   
select @LowerBound = ((@PageIndex) * @PageSize)+1
select @UpperBound = (@PageIndex+1) * @PageSize+1

IF (Len(@Filters)>0)
BEGIN
    SET @Filters = @Filters + '~'
    SET @Pos = charindex('~',@Filters)
    WHILE (@pos <> 0)
    BEGIN
        SET @NextFilter = substring(@Filters,1,@Pos - 1)
        SET @SubPos = charindex('=',@NextFilter)
        insert into #Filters (ModelEntityId, ValueText) Values (substring(@NextFilter, 1, @SubPos-1),substring(@NextFilter,@subPos+1, len(@NextFilter))) 
        SET @Filters = substring(@Filters,@pos+1,len(@Filters))
        SET @pos = charindex('~',@Filters)
    END     

    INSERT INTO #SelectedRecords    
        select  row,
               ContainerModelEntityId,
               DataContainerId, 
               DataInstanceId,
               ParentDataContainerId           
        from
        (
            select row_number() over (order by dv.valuetext) as row,
                   filtered.ContainerModelEntityId,
                   filtered.ParentDataContainerId, 
                   filtered.DataContainerId, 
                   filtered.DataInstanceId                    
            from dataValue dv
            join 
            (
                select dc.ModelEntityId as 'ContainerModelEntityId', 
                       di.DataInstanceId, 
                       di.DataContainerId,
                       dc.ParentDataContainerId 
                from datainstance di
                    join datavalue dv on di.Datainstanceid = dv.datainstanceid
                    join datacontainer dc on dc.DataContainerId = di.datacontainerId
                    join #filters f on dv.ModelEntityId = f.ModelEntityId and f.ValueText = dv.ValueText
                where ISNULL(dc.ParentDataContainerId,0) = ISNULL(null,0) and di.IsCurrent = 1 and di.ModelEntityId = @ContainerModelEntityId
                group by dc.ModelEntityId, dc.ParentDataContainerId, di.DataInstanceId, di.DataContainerId
                having (count(di.DataInstanceId) = (select count(ModelEntityId) from #Filters) ) 
            )
            filtered on filtered.dataInstanceId = dv.dataInstanceId
            where dv.ModelEntityId = @SortFieldId
        ) tbl
        WHERE row >= @LowerBound AND 
              row < @UpperBound 
END
ELSE
BEGIN
    INSERT INTO #SelectedRecords
    SELECT Row, ContainerModelEntityId, DataContainerId, DataInstanceId, ParentDataContainerId 
    FROM
    ( 
        select ROW_NUMBER() OVER (ORDER BY dv.ValueText) AS row,
               di.ModelEntityId as 'ContainerModelEntityId', 
               dc.DataContainerId, 
               di.DataInstanceId, 
               dv.ModelEntityId, 
               dc.ParentDataContainerId          
        from datacontainer dc
            inner join dataInstance di on dc.DataContainerId = di.DataContainerId
            left outer join dataValue dv on di.DataInstanceId = dv.DataInstanceId and dv.ModelEntityId=@SortFieldId
        where (@ParentRecordId is NULL or ISNULL(dc.ParentDataContainerId,0) = ISNULL(@ParentRecordId,0)) and 
               di.IsCurrent = 1 and di.ModelEntityId=@ContainerModelEntityId
    ) tbl
    WHERE tbl.row >= @LowerBound AND
          tbl.row < @UpperBound
END 


DECLARE @Count int
SELECT @Count = (SELECT COUNT(*) FROM DataContainer dc
INNER JOIN DataInstance di ON di.DataContainerId = dc.DataContainerId
WHERE di.ModelEntityId=@ContainerModelEntityId AND ISNULL(dc.ParentDataContainerId,0) = ISNULL(@ParentRecordId,0) AND di.IsCurrent=1)

    SELECT ContainerModelEntityId, DataContainerId, ParentDataContainerId, isnull(dv.ModelEntityId, @sortFieldId) as 'ModelEntityId', dv.ValueText, 
        @Count [TotalRecords] FROM
    #SelectedRecords sr  
    left outer join dataValue dv ON sr.DataInstanceId = dv.DataInstanceId
    ORDER BY
    CASE
        WHEN @Ascending = 1 THEN (RANK() OVER (ORDER BY sr.row ASC))
        WHEN @Ascending = 0 THEN (RANK() OVER (ORDER BY sr.row DESC))
    END

END