【问题标题】:Query works as expected, SSRS finds error?查询按预期工作,SSRS 发现错误?
【发布时间】:2020-07-06 18:52:37
【问题描述】:

此问题已关闭,因为有人认为它与 SSRS multi-value parameter using a stored procedure 是同一问题

但事实并非如此。我的报告不是存储过程,因此行为不同。此外,如果使用多值参数,此问题描述了没有结果的结果,并且对于这种情况也是不准确的。所以我会尝试再次发布。

我的报告大部分都有效。当我从 2 个特定参数(@global、@manual)中选择多个值时,我会收到此错误:

这里是 SQL:

DECLARE @STATE VARCHAR(2) = 'mn'
    ,@START DATE = '6/1/2020'
    ,@END DATE = '7/1/2020'
    ,@GLOBAL VARCHAR(50) = 'indigent fee'
    ,@MANUAL VARCHAR(100) = '''misc charges'',''discount'''

DROP TABLE

IF EXISTS #customers
    ,#test
    SELECT DISTINCT ch.amount
        ,ch.vehicle_program_id
        ,c.customer_id
        ,ch.customer_charge_id
        ,ch.charge_type
    INTO #customers
    FROM customer c
    JOIN customer_charge ch(NOLOCK) ON c.customer_id = ch.customer_id
    JOIN service_history sh(NOLOCK) ON sh.customer_id = c.customer_id
    JOIN header h(NOLOCK) ON h.service_history_id = sh.service_history_id
    WHERE ch.entry_date BETWEEN @START
            AND @END
        AND ch.price_trigger_id IN (
            16
            ,15
            )
        AND ch.source_type = 1
        AND sh.service_type = 5
        AND h.is_duplicate = 0;

WITH CTE_global
AS (
    SELECT DISTINCT ch.charge_type
        ,'global' AS type
    FROM customer_charge ch
    JOIN store s ON ch.store_id = s.store_id
    JOIN address a ON a.id = s.address_id
    JOIN locality l ON a.locality_id = l.id
    WHERE l.region = @state
        AND ch.price_trigger_id = 16
    
    UNION ALL
    
    SELECT 'None'
        ,'global'
    )
    ,CTE_manual
AS (
    SELECT DISTINCT ch.charge_type
        ,'manual' AS type
    FROM customer_charge ch
    JOIN store s ON ch.store_id = s.store_id
    JOIN address a ON a.id = s.address_id
    JOIN locality l ON a.locality_id = l.id
    WHERE l.region = @state
        AND ch.price_trigger_id = 15
    
    UNION ALL
    
    SELECT 'None'
        ,'manual'
    )
SELECT DISTINCT c.last_name
    ,c.first_name
    ,vp.account_no
    ,cust.charge_type
    ,cust.amount
    ,sh.service_date
    ,s.store_name_short
    ,GLOBAL = g.charge_type
    ,manual = m.charge_type
INTO #test
FROM vehicle_program vp(NOLOCK)
JOIN vehicle v(NOLOCK) ON v.vehicle_id = vp.vehicle_id
JOIN service_history sh(NOLOCK) ON sh.vehicle_program_id = vp.program_id
    AND service_type = 5
JOIN customer c(NOLOCK) ON v.customer_id = c.customer_id
    AND c.customer_id = sh.customer_id
JOIN store s(NOLOCK) ON vp.current_store_id = s.store_id
JOIN #customers cust ON cust.customer_id = c.customer_id
    AND cust.vehicle_program_id = sh.vehicle_program_id
JOIN customer_condition cc(NOLOCK) ON c.customer_id = cc.customer_id
JOIN customer_charge ch(NOLOCK) ON ch.customer_id = c.customer_id
JOIN service_charge sc ON sc.service_history_id = sh.service_history_id
    AND sc.customer_charge_id = cust.customer_charge_id
JOIN header h(NOLOCK) ON h.service_history_id = sh.service_history_id
JOIN CTE_global g ON g.charge_type = ch.charge_type
JOIN CTE_manual m ON m.charge_type = ch.charge_type
WHERE cc.state_of_conviction = @state
    AND sh.service_date BETWEEN @START
        AND @END
    AND h.is_duplicate = 0

SELECT *
FROM #test
WHERE GLOBAL IN (
        CASE 
            WHEN @global IN ('None')
                THEN charge_type
            WHEN @global NOT IN ('None')
                THEN @global
            END
        )
    OR manual IN (
        CASE 
            WHEN @manual IN ('None')
                THEN charge_type
            WHEN @manual NOT IN ('None')
                THEN @manual
            END
        )

为了清楚起见,查询中的最后一位有一些逻辑允许这两个参数是可选的:因此通过选择“无”,该参数基本上变得无用。很明显,问题出在最后一点,特别是我使用 CASE 表达式的 WHERE 子句。当我删除它时,我没有收到错误,但我当然失去了我的逻辑。最令人困惑的是,错误表明逗号有问题,但 SQL 的那部分没有逗号??任何帮助将不胜感激。

【问题讨论】:

  • 抱歉,您的查询在通过 SSMS 执行时无法正常工作。您在假设 IN 如何与变量一起工作时犯了一个常见错误。 db 引擎不会神奇地将变量扩展为一组以进行比较-您的使用是一个附加问题。但是当@manual 包含您分配的值时,比较when @manual in ('NONE')(或其他任何东西——比如“折扣”)永远不会是真的。但是该逻辑错误似乎被以下 WHEN 表达式所掩盖,该表达式始终为真(如果不为空)。
  • TBH 这一切似乎太复杂了。但这需要投资才能弄清楚您要做什么。但是你不应该是splattering your code with NOLOCK,如果你这样做了,你不应该使用不推荐使用的语法来这样做。

标签: sql-server reporting-services


【解决方案1】:

假设用户只会从它自己的列表中选择“无”并且永远不会选择其他值,那么以下应该可以工作。

WHERE (GLOBAL IN (@Global) OR @Global = 'None')
      AND 
      (manual IN (@manual) OR @manual = 'None')

【讨论】:

    【解决方案2】:

    此问题已关闭,因为有人认为这是同一个问题

    这是一个骗局,但您必须在其他答案的字里行间阅读才能将其应用于这种情况。关键是 SSRS 在查询正文中用分隔字符串替换了多选参数,这种转换可能导致意外没有结果,或者导致非法 SQL 查询,具体取决于参数标记在原始查询中出现的位置。

    我会更清楚地说明发生了什么。您可以将此行为作为您的数据集查询来重现:

    drop table if exists #foo 
    
    create table #foo(charge_type varchar(200) , global varchar(200))
    
        select *
        from #foo 
        WHERE GLOBAL IN (
                CASE 
                    WHEN @global IN ('None')
                        THEN charge_type
                    WHEN @global NOT IN ('None')
                        THEN @global
                    END
                )
    

    并将@global配置为允许多选的参数。当用户选择多个值时,SSRS 将查询转换为:

    drop table if exists #foo 
    
    create table #foo(charge_type varchar(200) , global varchar(200))
    select *
    from #foo 
    WHERE GLOBAL IN (
            CASE 
                WHEN N'a',N'b' IN ('None')
                    THEN charge_type
                WHEN N'a',N'b' NOT IN ('None')
                    THEN N'a',N'b'
                END
            )
    

    An expression of non-boolean type specified in a context where a condition is expected, near ','. 失败

    【讨论】:

      猜你喜欢
      • 2011-02-27
      • 1970-01-01
      • 2012-11-13
      • 2015-09-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多