如何编写多参数CTE脚本?

时间:2013-03-14 21:35:14

标签: tsql common-table-expression

我正在尝试为SSRS报告编写TSQL脚本,该报告使用CTE根据所选参数选择记录。我正在寻找最有效的方法来做到这一点,无论是在TSQL和/或SSRS中。我有4个参数可以设置为NULL(所有值)或一个特定值。然后在我的CTE中,我有以下几行:

    ROW_NUMBER() over(partition by G.[program_providing_service],G.people_id
    order by G.[actual_date] desc) as rowID

以上CTE适用于Program为NULL且People不为null的情况。我的4个参数是:

计划,设施,员工和人员。

所以我只想在值为NULL时对值进行分区。目前,我根据参数值通过一个CTE实现此功能。例如,如果他们为除People之外的所有参数选择NULL,则此CTE将如下所示:

    ROW_NUMBER() over(partition by G.people_id
    order by G.[actual_date] desc) as rowID

或者如果所有5个参数都为空:

    ROW_NUMBER() over(partition by G.[program_providing_service], G.[site_providing_service], G.staff_id, G.people_id
    order by G.[actual_date] desc) as rowID

如果他们没有为4个参数中的任何一个选择NULL,那么我可能不需要按任何字段进行分区,因为我只想通过actual_date降序排序前1条记录。这就是我的CTE的样子:

;with cte as
(
Select    distinct
    G.[actual_date],
    G.[site_providing_service],
    p.[program_name],
    G.[staff_id],
    G.program_providing_service,
    ROW_NUMBER() over(partition by G.[program_providing_service],G.people_id
    order by G.[actual_date] desc) as rowID

From 
event_log_rv G With (NoLock)

WHERE 
...
AND (@ClientID Is Null OR [people_id]=@ClientID)
AND (@StaffID Is Null OR [staff_id] = @StaffID)
AND (@FacilityID Is Null OR [site_providing_service] = @FacilityID)
AND (@ProgramID Is Null OR [program_providing_service] = @ProgramID)
and (@SupervisorID is NULL OR staff_id in (select staff_id from #supervisors))
)
SELECT 
    [actual_date],
    [site_providing_service],
    [program_name],
    [staff_id],
    program_providing_service,
    people_id,
    rowID

FROM cte WHERE rowid = 1
ORDER BY [Client_FullName]

其中ROW_NUMBER行根据所选参数而变化。目前,我在此TSQL脚本中有5个IF语句,如下所示:

IF @ProgramID IS NOT NULL AND @ClientID IS NULL
BEGIN
...
END

with one CTE in each of these IF statements:

IF @FacilityID IS NOT NULL AND @ClientID IS NULL
BEGIN
...

END

IF @ProgramID IS NOT NULL AND @ClientID IS NULL
BEGIN
...
END

IF @StaffID IS NOT NULL AND @ClientID IS NULL
BEGIN
...

END

IF @ClientID IS NOT NULL
BEGIN
...
END

如何为所有可能的选项编码,无论他们选择NULL还是特定值?

1 个答案:

答案 0 :(得分:1)

OMG ....我花了很长时间才想要了解你想做什么。你的描述中有一些矛盾。请求取消您的描述。就像你说的那样,你只想在值为NULL时对值进行分区;然后你也说过,当他们为除人之外的所有参数选择NULL时,你就会对人进行分区....

无论你想以什么方式实现,在'null'或'not null'上进行分区,你可以构造动态sql来实现这一点,而不是添加很多[if ... else]

以下代码是伪的,绝对没有经过测试。只是给你一个提示。以下代码有一个假设,即您的参数在分区顺序中具有优先级,例如,如果Program不为null(或为null),则Program位于第一个位置。

    declare @sql varchar(max)
    set @sql = '
    ;with cte as
    (
    Select    distinct
        G.[actual_date],
        G.[site_providing_service],
        p.[program_name],
        G.[staff_id],
        G.program_providing_service,
        ROW_NUMBER() over(partition by
    '
    if(@progarm is null)
       set @sql = @sql + 'G.[program_providing_service],'
    if(@facility is null) 
       set @sql = @sql + 'G.[site_providing_service],'
    if(@staff is null )
       set @sql = @sql + 'G.staff_id,'
    if(@people is null)
       set @sql = @sql + 'G.people_id'
    set @sql = @sql + '
        order by G.[actual_date] desc) as rowID
    From 
    event_log_rv G With (NoLock)
    WHERE 
    ...
    AND (@ClientID Is Null OR [people_id]=@ClientID)
    AND (@StaffID Is Null OR [staff_id] = @StaffID)
    AND (@FacilityID Is Null OR [site_providing_service] = @FacilityID)
    AND (@ProgramID Is Null OR [program_providing_service] = @ProgramID)
    and (@SupervisorID is NULL OR staff_id in (select staff_id from #supervisors))
    )
    SELECT 
        [actual_date],
        [site_providing_service],
        [program_name],
        [staff_id],
        program_providing_service,
        people_id,
        rowID
    FROM cte WHERE rowid = 1
    ORDER BY [Client_FullName]
    '
    exec(@sql)