case语句中的动态where子句

时间:2014-08-19 17:37:10

标签: sql sql-server sql-server-2008 sql-server-2008-r2 where-clause

我被置于case语句中的动态where子句中。这是我的SQL块。

Select EstimatedCharges = CASE 
   WHEN EXISTS (
        SELECT 1
        FROM ResidualOverrideConfiguration
        WHERE FacilityCode = @FacilityCode
        AND DRGCode = DRG.DRG AND COALESCE(IsPayorPlanEstimateEnabled, 1) = 1
        AND ChargeAmount IS NOT NULL
        AND COALESCE(FacilityPlanCode, @PrimaryPlanCode) = @PrimaryPlanCode
        AND COALESCE(PatientType, @PatientType) = @PatientType
        AND COALESCE(FacilityPatientType, @FacilityPatientType) = @FacilityPatientType
        AND COALESCE(ServiceFieldCode, @ServiceFieldCode) = @ServiceFieldCode
    )
    THEN (PICK_SOME_FIELD)
  FROM SOME_TABLE

以下是我的表,

enter image description here

在此表中,FacilityPlanCode,ServiceFieldCode,FacilityPatientType,PatientType是正在使用的可选字段。 FacilityCode,DRGCode,ChargeAmount and IsPayorPlanEstimateEnabled是强制性的。

我的要求是,如果可选字段为空或空白,则它不应该是where条件的一部分。

例如,如果FacilityPlancode= null, PatientType=Null,那么案例中的Select查询就会这样,

SELECT 1
FROM ResidualOverrideConfiguration
WHERE FacilityCode = @FacilityCode
    AND DRGCode = DRG.DRG
    AND COALESCE(IsPayorPlanEstimateEnabled, 1) = 1
    AND ChargeAmount IS NOT NULL
    AND COALESCE(FacilityPatientType, @FacilityPatientType) = @FacilityPatientType
    AND COALESCE(ServiceFieldCode, @ServiceFieldCode) = @ServiceFieldCode

帮帮我。

我需要什么

如果可选字段为空,那么我需要一种方法来完全忽略它们,假设它们不在子句中。

1 个答案:

答案 0 :(得分:0)

我认为您应该使用动态Sql来构建查询,并且只添加实际传递值的变量。

像......一样......

DECLARE @Sql NVARCHAR(MAX);


SET @Sql = N'Select EstimatedCharges = CASE 
                   WHEN EXISTS (
                        SELECT 1
                        FROM ResidualOverrideConfiguration
                        WHERE FacilityCode = @FacilityCode
                        AND DRGCode = DRG.DRG AND COALESCE(IsPayorPlanEstimateEnabled, 1) = 1
                        AND ChargeAmount IS NOT NULL '
                + CASE WHEN @PrimaryPlanCode IS NOT NULL THEN 
                         N' AND (COALESCE(FacilityPlanCode, @PrimaryPlanCode) = @PrimaryPlanCode) ' ELSE N' ' END
                + CASE WHEN @PatientType IS NOT NULL THEN 
                         N' AND (COALESCE(PatientType, @PatientType) = @PatientType) '              ELSE N' ' END
                + CASE WHEN @FacilityPatientType IS NOT NULL THEN 
                         N' AND (COALESCE(FacilityPatientType, @FacilityPatientType) = @FacilityPatientType) '
                                                                                                     ELSE N' ' END
                + CASE WHEN @ServiceFieldCode IS NOT NULL THEN 
                         N' AND (COALESCE(ServiceFieldCode, @ServiceFieldCode) = @ServiceFieldCode)' ELSE N' ' END
                +   N' )
                    THEN PICK_SOME_FIELD
                  FROM SOME_TABLE'

EXECUTE sp_executesql @Sql
                     ,N'@FacilityCode INT, @PrimaryPlanCode INT, ......'
                     ,@FacilityCode
                     ,@PrimaryPlanCode

其他方法的问题

这种其他方法存在一个主要问题,你可以在where where子句中编写类似......

的内容
WHERE ( PrimaryPlanCode = @PrimaryPlanCode  OR @PrimaryPlanCode IS NULL)

这种方法的两个主要问题

1)你不能强制SQL Server首先检查一个表达式,就像@PrimaryPlanCode IS NULL一样,Sql Server可能决定先评估表达式PrimaryPlanCode = @PrimaryPlanCode,这样你就可以对where子句进行求值,即使变量也是如此value为null。

2)SQL Server不执行Short-Circuiting,即使它决定先检查@PrimaryPlanCode IS NULL表达式,即使它的计算结果为true,SQL Server仍然可以继续进行评估{{}中的其他表达式1}}子句。

因此,对于像这样的查询,请坚持使用Dynamic Sql。和快乐的日子。