检查是否在多值参数中选择了逗号分隔列表中的任何值(在SQL数据集中)

时间:2019-04-25 14:04:47

标签: sql tsql reporting-services

我的SQL数据集中有一个字段,其中包含一个由2-4个短字母代码组成的逗号分隔列表-我们称其为CodeField。我还有一个多值报告参数,其可用值是所有可能的代码集-CodeParam。 基本上,在我的SQL查询中,我需要包含一个WHERE条件,其中包含在CodeParam中选择了CodeField中的 any 代码的行。

我最初的方法是生成以下形式的条件(通过自定义代码或SSRS表达式中的JOIN): ([CodeField] LIKE '%AA%') OR ([CodeField] LIKE '%BB%') OR .. (其中AA,BB,..是在CodeParam中选择的值),然后根据this answer将其包括为动态SQL。

但是,那里的评论表明,动态生成的SQL通常是处理问题的错误方法,并且可能还有更好的方法。

那么,解决此问题的最佳方法是什么? 不必过分担心查询的性能;我主要是在寻找最简单/最有效的解决方案。

1 个答案:

答案 0 :(得分:0)

因此,我肯定会提到,出于这个确切原因,拥有包含多个数据点的列往往不是理想的选择。

无论如何,我建议做的事情如下:

  1. 我们为每个唯一的多值列分配一个RowId。
  2. 我们用定界符将列分开(我使用了https://stackoverflow.com/a/28153222/1470896,但是有更好的方法可以通过存储过程来做到这一点)。
  3. 我们使用IN进行匹配,并保留匹配的不同RowIds
  4. 我们通过匹配的RowId过滤原始结果集

这是一个例子

IF OBJECT_ID('tempdb..#Temp') IS NOT NULL DROP TABLE #Temp

SELECT
    *
    , ROW_NUMBER() OVER (ORDER BY NEWID()) AS RowId
INTO #Temp
FROM (VALUES ('abc,def,ghi,jkl'), ('mno,pqr,stu,vwx')) AS MyTable(MyColumn);

WITH StringSplitWithRowId AS (
    SELECT
        RowId
        , LTRIM(RTRIM(Split.a.value('.', 'VARCHAR(100)'))) 'Value'
    FROM (
        SELECT
            RowId
            , CAST('<M>' + REPLACE( MyColumn, ',', '</M><M>') + '</M>' AS XML) AS Data
        FROM #Temp
    ) a
    CROSS APPLY Data.nodes ('/M') AS Split(a)
),

RowIdsToInclude AS (
SELECT DISTINCT
    RowId
FROM StringSplitWithRowId
WHERE Value IN (@SsrsReportParameter) -- query will not work in ssms, needs to be run in RS
)

SELECT
    *
FROM #Temp t
INNER JOIN RowIdsToInclude i
ON t.RowId = i.RowId