web-dev-qa-db-fra.com

Passage de plusieurs valeurs pour un seul paramètre dans Reporting Services

J'ai plusieurs paramètres de sélection multiple dans mon rapport. J'essaie de trouver un moyen de transmettre plusieurs valeurs pour un seul paramètre dans la chaîne de requête Web? Si je passe dans une seule valeur, cela fonctionne bien.

Le rapport fonctionne correctement en sélectionnant plusieurs choix pour un seul paramètre. Mon problème réside dans la chaîne de requête Web.

64

Bien que la solution de John Sansom fonctionne, il existe un autre moyen de le faire, sans avoir à utiliser un fichier UDF ..__ scalaire potentiellement inefficace. Dans le rapport SSRS, sous l'onglet Paramètres de la définition de requête, définissez la valeur du paramètre sur 

=join(Parameters!<your param name>.Value,",")

Dans votre requête, vous pouvez ensuite référencer la valeur comme suit:

where yourColumn in (@<your param name>)
93
Ed Harper

C'est ce que j'utilise lorsque je passe un paramètre multi-select à un autre paramètre multi-select.

=SPLIT(JOIN(Parameters!<your param name>.Value,","),",")
40
Minks

C'est l'une des fonctionnalités peu prises en charge dans SQL Reporting Services.

Ce que vous devez faire est de transmettre tous les éléments sélectionnés sous forme de chaîne unique à votre procédure stockée. Chaque élément de la chaîne sera séparé par une virgule.

Ce que je fais alors est de scinder la chaîne en utilisant une fonction qui renvoie la chaîne fournie sous forme de tableau. Voir ci-dessous.

ALTER FUNCTION [dbo].[fn_MVParam]
   (@RepParam nvarchar(4000), @Delim char(1)= ',')
RETURNS @Values TABLE (Param nvarchar(4000))AS
  BEGIN
  DECLARE @chrind INT
  DECLARE @Piece nvarchar(100)
  SELECT @chrind = 1 
  WHILE @chrind > 0
    BEGIN
      SELECT @chrind = CHARINDEX(@Delim,@RepParam)
      IF @chrind  > 0
        SELECT @Piece = LEFT(@RepParam,@chrind - 1)
      ELSE
        SELECT @Piece = @RepParam
      INSERT  @Values(Param) VALUES(CAST(@Piece AS VARCHAR))
      SELECT @RepParam = RIGHT(@RepParam,LEN(@RepParam) - @chrind)
      IF LEN(@RepParam) = 0 BREAK
    END
  RETURN
  END

Vous pouvez ensuite référencer les résultats dans la clause where de votre requête principale comme suit:

where someColumn IN(SELECT Param FROM dbo.fn_MVParam(@sParameterString,','))

J'espère que cette solution vous sera utile. S'il vous plaît n'hésitez pas à poser toutes les questions que vous pourriez avoir.

À la vôtre, John

21
John Sansom

John Sansom et Ed Harper ont d'excellentes solutions. Cependant, j’ai été incapable de les faire fonctionner lorsqu’il s’agissait de champs d’ID (par exemple, des entiers). J'ai modifié la fonction split ci-dessous pour CAST les valeurs sous forme d'entiers afin que la table se joigne aux colonnes de clé primaire. J'ai également commenté le code et ajouté une colonne pour ordre, au cas où l'ordre de la liste délimitée serait significatif.

CREATE FUNCTION [dbo].[fn_SplitInt]
(
    @List       nvarchar(4000),
    @Delimiter  char(1)= ','
)
RETURNS @Values TABLE
(
    Position int IDENTITY PRIMARY KEY,
    Number int
)

AS

  BEGIN

  -- set up working variables
  DECLARE @Index INT
  DECLARE @ItemValue nvarchar(100)
  SELECT @Index = 1 

  -- iterate until we have no more characters to work with
  WHILE @Index > 0

    BEGIN

      -- find first delimiter
      SELECT @Index = CHARINDEX(@Delimiter,@List)

      -- extract the item value
      IF @Index  > 0     -- if found, take the value left of the delimiter
        SELECT @ItemValue = LEFT(@List,@Index - 1)
      ELSE               -- if none, take the remainder as the last value
        SELECT @ItemValue = @List

      -- insert the value into our new table
      INSERT INTO @Values (Number) VALUES (CAST(@ItemValue AS int))

      -- remove the found item from the working list
      SELECT @List = RIGHT(@List,LEN(@List) - @Index)

      -- if list is empty, we are done
      IF LEN(@List) = 0 BREAK

    END

  RETURN

  END

Utilisez cette fonction comme indiqué précédemment avec:

WHERE id IN (SELECT Number FROM dbo.fn_SplitInt(@sParameterString,','))
8
CodeGrue

J'ai rencontré un problème avec le magnifique fn_MVParam . SSRS 2005 a envoyé des données avec une apostrophe sous forme de 2 guillemets.

J'ai ajouté une ligne pour résoudre ce problème.

select @RepParam = replace(@RepParam,'''''','''')

Ma version de la fn utilise également varchar au lieu de nvarchar.

CREATE FUNCTION [dbo].[fn_MVParam]
   (
    @RepParam varchar(MAX),
    @Delim char(1)= ','
   )
RETURNS @Values TABLE (Param varchar(MAX)) AS
/*
  Usage:  Use this in your report SP 
     where ID in (SELECT Param FROM fn_MVParam(@PlanIDList,','))
*/

BEGIN

   select @RepParam = replace(@RepParam,'''''','''')
   DECLARE @chrind INT
   DECLARE @Piece varchar(MAX)
   SELECT @chrind = 1
   WHILE @chrind > 0
      BEGIN
         SELECT @chrind = CHARINDEX(@Delim,@RepParam)
         IF @chrind > 0
            SELECT @Piece = LEFT(@RepParam,@chrind - 1)
         ELSE
            SELECT @Piece = @RepParam
         INSERT @VALUES(Param) VALUES(@Piece)
         SELECT @RepParam = RIGHT(@RepParam,DATALENGTH(@RepParam) - @chrind)
         IF DATALENGTH(@RepParam) = 0 BREAK
      END
   RETURN
END
4
Bob Amy

Oracle:

La phrase "IN" (Solution d'Ed) ne fonctionne pas avec une connexion Oracle (au moins la version 10). Cependant, nous avons trouvé ce moyen simple de contourner le problème. À l'aide de l'onglet du paramètre du jeu de données, convertissez le paramètre multivaleur en un fichier CSV:

    :name =join(Parameters!name.Value,",")

Ensuite, dans la clause WHERE de votre instruction SQL, utilisez la fonction instring pour rechercher une correspondance.

    INSTR(:name, TABLE.FILENAME) > 0
4
Jeff

Modification de la grande solution de Jean, résolvez:

  • Erreur "2 citations"
  • espace après pièce de paramètre

    
    ALTER FUNCTION [dbo].[fn_MVParam]
    (@RepParam nvarchar(4000), @Delim char(1)= ',')
    RETURNS @Values TABLE (Param nvarchar(4000))AS
    BEGIN
    //2 quotes error
    set @RepParam = replace(@RepParam,char(39)+char(39),CHAR(39))
    DECLARE @chrind INT
    DECLARE @Piece nvarchar(100)
    SELECT @chrind = 1 
    WHILE @chrind > 0
    BEGIN
      SELECT @chrind = CHARINDEX(@Delim,@RepParam)
      IF @chrind  > 0
        SELECT @Piece = LEFT(@RepParam,@chrind - 1)
      ELSE
        SELECT @Piece = @RepParam
      INSERT  @Values(Param) VALUES(CAST(@Piece AS VARCHAR(300)))
      //space after one of piece in parameter: LEN(@RepParam + '1')-1
      SELECT @RepParam = RIGHT(@RepParam,LEN(@RepParam + '1')-1 - @chrind)
      IF LEN(@RepParam) = 0 BREAK
    END
    RETURN
    END
    
3
grum

Donc, multiplier les valeurs de texte aboutirait dans la requête avec des guillemets simples autour de chaque signe utilisé = rejoindre (Paramètres! Client.Value, "','"). Ainsi, après ".Value", c’est virgule, guillemet double, guillemet simple, virgule, guillemet simple, guillemet double, parenthèse serrée. simples :)

1
RichardBSmith

La solution ci-dessous a fonctionné pour moi.

  1. Dans l'onglet Paramètres de vos propriétés de jeu de données, cliquez sur l'icône d'expression (! http://chittagongit.com//images/fx-icon/fx-icon-16.jpg [symbole fx]) en regard du paramètre que vous Il faut autoriser une entrée délimitée par des virgules pour. 

  2. Dans la fenêtre d’expression qui apparaît, utilisez la fonction Séparer (Fonctions communes -> Texte). Exemple ci-dessous:

= Split (Paramètres! ParameterName.Value, ",")

1
sherebry

Il serait probablement plus facile d’ajouter d’abord les valeurs multiples à une table, puis de les rejoindre ou ce que vous voulez (même avec des caractères génériques) ou d’enregistrer les données dans une autre table pour une utilisation ultérieure (ou même d’ajouter les valeurs à une autre table) .

Définissez la valeur du paramètre via l'expression dans l'ensemble de données:

="SELECT DISTINCT * FROM (VALUES('" & JOIN(Parameters!SearchValue.Value, "'),('") & "')) 
AS tbl(Value)"

La requête elle-même:

DECLARE @Table AS TABLE (Value nvarchar(max))

INSERT INTO @Table EXEC sp_executeSQL @SearchValue 

Exemple de caractère générique:

SELECT * FROM YOUR_TABLE yt 

INNER JOIN @Table rt ON yt.[Join_Value] LIKE '%' + rt.[Value] + '%'

J'aimerais trouver un moyen de le faire sans SQL dynamique, mais je ne pense pas que cela fonctionnera à cause de la façon dont SSRS transmet les paramètres à la requête. Si quelqu'un sait mieux, s'il vous plaît faites le moi savoir.

1
jon

Il s’agit d’utiliser la fonction join pour enregistrer un paramètre multivaleur, puis de restaurer ultérieurement les mêmes sélections exactes dans la base de données.

Je viens juste de terminer un rapport pour lequel les paramètres devaient être sauvegardés. Lorsque le rapport est rouvert (le rapport reçoit le paramètre OrderID), les valeurs précédemment choisies par l'utilisateur doivent être à nouveau sélectionnées.

Le rapport utilisait une demi-douzaine de paramètres, chacun ayant son propre ensemble de données et sa liste déroulante. Les paramètres dépendaient des paramètres précédents pour réduire la portée de la sélection finale. Lorsque le rapport était "affiché", une procédure stockée était appelée à remplir.

La procédure stockée a reçu chacun des paramètres qui lui ont été transmis à partir du rapport. Il a vérifié une table de stockage dans la base de données pour voir si des paramètres avaient été enregistrés pour cet ID de commande. Sinon, tous les paramètres ont été sauvegardés. Si tel est le cas, il a mis à jour tous les paramètres pour cette commande (c'est le cas où l'utilisateur change d'avis ultérieurement). 

Lorsque le rapport est exécuté, il existe un ensemble de données dsParameters, qui est un texte SQL qui sort et qui sélectionne la seule ligne pour cet ID de commande s'il en existe un. Chacun des paramètres du rapport tire sa valeur par défaut de cet ensemble de données et sa liste de sélection d'un ensemble de données dédié à ce paramètre.

J'ai eu des problèmes avec le paramètre de sélection multiple. J'ai utilisé une commande join (@Value, ",") dans la liste de paramètres de l'ensemble de données principale, en transmettant à la procédure stockée une chaîne délimitée par des virgules. Mais comment le restaurer? Vous ne pouvez pas insérer la chaîne délimitée par des virgules dans la zone des valeurs par défaut du paramètre.

J'ai dû créer un autre jeu de données pour scinder le paramètre, d'une manière similaire à ce dont vous parlez. Cela ressemble à ceci:

IF OBJECT_ID('tempdb..#Parse','U') IS NOT NULL DROP TABLE #Parse

DECLARE @Start int, @End int, @Desc varchar(255)

SELECT @Desc = fldDesc FROM dbCustomData.dbo.tblDirectReferralFormParameters WHERE fldFrom = @From and fldOrderID = @OrderID

CREATE TABLE #Parse (fldDesc varchar(255))

SELECT @Start = 1, @End = 1

WHILE @End > 0
    BEGIN
        SET @End = CHARINDEX(',',@Desc,@Start)
        IF @End = 0 
            BEGIN
                INSERT #Parse SELECT REPLACE(SUBSTRING(@Desc,@Start,LEN(@Desc)),',','') AS fldDesc 
                BREAK
            END
        ELSE        
            BEGIN
                INSERT #Parse SELECT REPLACE(SUBSTRING(@Desc,@Start,@End-@Start),',','') AS fldDesc 
            END
        SET @Start = @End + 1
    END

SELECT * FROM #Parse

À chaque ouverture du formulaire, cet ensemble de données recherche dans la base de données une chaîne enregistrée pour ce paramètre à plusieurs valeurs. S'il n'y en a pas, il retourne null. S'il est activé, il analyse les virgules et crée une ligne pour chacune des valeurs.

Ensuite, la zone des valeurs par défaut est définie sur cet ensemble de données et sur fldDesc. Ça marche! Lorsque j'en choisis un ou plusieurs, ils sauvegardent et se reconstituent lorsque le formulaire est ouvert à nouveau.

J'espère que ça aide. J'ai cherché pendant un moment et je n'ai trouvé aucune mention de l'enregistrement de la chaîne de jointure dans une base de données, puis de son analyse dans un ensemble de données.

1
Scott

Juste un commentaire - je me suis retrouvé dans un monde de souffrance en essayant de faire fonctionner une clause IN en connexion avec Oracle 10g. Je ne pense pas que la requête réécrite puisse être correctement transmise à une base de données de 10 g. Je devais abandonner complètement la multi-valeur. La requête ne renverrait des données que lorsqu'une seule valeur (à partir du sélecteur de paramètres à valeurs multiples) a été choisie. J'ai essayé les pilotes MS et Oracle avec les mêmes résultats. J'aimerais savoir si quelqu'un a eu du succès avec ça.

1
ScottLenart

Ce que vous pouvez également faire, c'est ajouter ce code dans votre procédure stockée:

set @s = char(39) + replace(@s, ',', char(39) + ',' + char(39)) + char(39)

(En supposant que @s est une chaîne à valeurs multiples (comme "A, B, C"))

1
Wilfred van Dijk

Je suis nouveau sur le site et je ne vois pas comment commenter une réponse précédente. C'est ce que je pense que cela devrait être. Je ne pouvais pas non plus voter pour le message de Jeff, ce qui, je crois, m'a donné ma réponse. Quoi qu'il en soit ...

Bien que je puisse voir comment fonctionnent certains des bons messages et des modifications ultérieures, je ne dispose que d'un accès en lecture à la base de données. Par conséquent, aucune solution UDF, SP ou basée sur la vue ne fonctionne pour moi. La solution d'Ed Harper semblait donc bonne, à l'exception du commentaire de VenkateswarluAvula selon lequel vous ne pouvez pas passer une chaîne séparée par des virgules en tant que paramètre dans une clause WHERE IN et vous attendre à ce qu'elle fonctionne comme vous le souhaitez. Mais la solution de Jeff à l’Oracle 10g comble cette lacune. Je les ai mises avec le billet de blog de Russell Christopher à http://blogs.msdn.com/b/bimusings/archive/2007/05/07/how-do-you-set-select-all-as-the- default-for-multi-value-parameters-in-reporting-services.aspx et j'ai ma solution:

Créez votre paramètre multi-sélection MYPARAMETER en utilisant n'importe quelle source de valeurs disponibles (probablement un jeu de données). Dans mon cas, la sélection multiple provenait d'un tas d'entrées TEXT, mais je suis sûre qu'avec quelques modifications, cela fonctionnerait avec d'autres types. Si vous voulez que Sélectionner tout soit la position par défaut, définissez la même source comme valeur par défaut. Cela vous donne votre interface utilisateur, mais le paramètre créé n'est pas le paramètre transmis à mon SQL. 

En passant au SQL, et à la solution de Jeff au problème WHERE IN (@MYPARAMETER), j’ai un problème personnel: 1 des valeurs ('Charge') apparaît dans l’une des autres valeurs ('Non Charge'). ), ce qui signifie que CHARINDEX pourrait trouver un faux positif. Je devais rechercher le paramètre pour la valeur délimitée à la fois avant et après. Cela signifie que je dois m'assurer que la liste séparée par des virgules comporte également une virgule de début et de fin. Et voici mon extrait de code SQL:

where ...
and CHARINDEX(',' + pitran.LINEPROPERTYID + ',', @MYPARAMETER_LIST) > 0

Le bit au milieu est de créer un autre paramètre (caché en production, mais pas en cours de développement) avec:

  • Un nom de MYPARAMETER_LIST
  • Un type de texte 
  • Une seule valeur disponible de ="," + join(Parameters!MYPARAMETER.Value,",") + "," et une étiquette qui
    n’a pas d’importance (puisqu'il ne sera pas affiché).
  • Une valeur par défaut exactement identique
  • Juste pour être sûr, j'ai défini l'option Toujours actualiser dans les deux paramètres Avancéproperties

C'est ce paramètre qui est transmis à SQL, qui est une chaîne pouvant faire l'objet d'une recherche, mais que SQL gère comme n'importe quel morceau de texte.

J'espère que l'assemblage de ces fragments de réponses aidera quelqu'un à trouver ce qu'il cherche.

1
Mark Belshaw

cela a fonctionné pour un ensemble distinct de chaînes (par exemple, "START", "FIN", "ERREUR", "SUCCÈS")

1) définir un paramètre de rapport (par exemple, @log_status) et cocher la case "Autoriser plusieurs valeurs"
 enter image description here

2) définir un jeu de données
3) ouvre la fenêtre dataset-properties
3a) dans l’onglet Requête, entrez votre requête: par ex.

select * from your_table where (CHARINDEX(your_column, @log_status,0) > 0)

3b) dans l'onglet Paramètres, entrez votre paramètre, par exemple.
Parametername: @log_status ; Parametervalue: <<Expr>> 
3c) pour l'Expr, cliquez sur le bouton "fx" et entrez:

=join(Parameters!log_status.Value,",")

 enter image description here

fini! (c'est similaire à la solution d'Ed Harper, mais désolé de dire que cela n'a pas fonctionné pour moi)

1
cjonas

Cela fonctionne très bien pour moi:

WHERE CHARINDEX(CONVERT(nvarchar, CustNum), @CustNum) > 0
1
user3688168
  1. Créer le jeu de données pour la liste dans le rapport
  2. Faites un clic droit sur le paramètre et sélectionnez les valeurs disponibles
  3. Sélectionner le jeu de données nouvellement créé en tant que jeu de données
  4. Ajouter la valeur transmise à la procédure stockée en tant que champ de valeur 
  5. Ajoutez la description du paramètre à la zone de libellé (si le paramètre est customerID, alors libellé peut être ex. NomClient.)
  6. Enfin, ajoutez le code suivant à votre procédure stockée

declare @paramName AS NVARCHAR (500),

SI RIGHT (@paramName, 1) = ',' DEBUT SET @ NomParam = LEFT ((@ NomParam, LEN ((@ NomParam) -1) FIN

1

Dans le passé, j'ai eu recours à des procédures stockées et à une fonction permettant de sélectionner plusieurs années dans une requête SQL Server pour les services de génération de rapports. L'utilisation de l'expression Join dans la valeur du paramètre de requête suggérée par Ed Harper ne fonctionnerait toujours pas avec une clause SQL IN dans l'instruction where. Ma résolution était d'utiliser ce qui suit dans la clause where avec le paramètre Join expression: et charindex (cast (Schl.Invt_Yr as char (4)), @Invt_Yr)> 0

0
J Steen

A partir de MSSQL 2016 - avec le niveau de compatibilité 130, vous pouvez utiliser String_Split() pour analyser votre paramètre joint à partir de SSRS. Supposons que vous souhaitiez renseigner un paramètre à partir d'une requête dans SSRS, puis le transmettre à un processus stocké ou à un ensemble de données partagé SSRS:

  1. Ajoutez deux jeux de données à votre rapport SSRS, un qui renvoie une liste de valeurs et d'étiquettes à afficher dans votre paramètre et l'autre qui contient les données que vous souhaitez filtrer. Chacun de ces ensembles de données peut être un proc stocké, un ensemble de données partagé ou une requête intégrée.
  2. Créez un paramètre dans SSRS qui n'est PAS dans l'ensemble de données que vous souhaitez filtrer. Appelons cela Customer
  3. Définissez Customer param pour autoriser plusieurs valeurs et configurez l'onglet Available Values avec l'ensemble de données, les étiquettes et les valeurs que vous souhaitez afficher à partir de la requête.
  4. Cliquez avec le bouton droit sur l'ensemble de données que vous souhaitez filtrer et ajoutez un paramètre que IS a défini dans la procédure stockée. Appelons cela CustomerList.
  5. Cliquez sur le bouton d'expression en regard du champ de valeur pour ce paramètre et faites Join(Parameters!Customer.Value, ",").
  6. Dans votre processus stocké ou partagé, utilisez string_split pour décomposer le paramètre @CustomerList délimité par des virgules dans un tableau: Customer.CustID in (select value from string_split(@CustomerList, ',') where value = Customer.CustID)
0
Robert Hartshorn

J'avais besoin d'une solution pour Oracle et j'ai trouvé que cela fonctionnait pour moi dans ma requête pour mon rapport pour DB> = 10g.

select * from where in ( select regexp_substr (, '[^,] +', 1, niveau) parmi dual connect by regexp_substr (, '[^,] +', 1, niveau) n'est pas nul )

source https://blogs.Oracle.com/aramamoo/entry/how_to_split_comma_separated_string_and_pass_to_in_clause_of_select_statement

0
Aaron

Si vous souhaitez transmettre plusieurs valeurs à RS via une chaîne de requête, il vous suffit de répéter le paramètre report pour chaque valeur. 

Par exemple; J'ai une colonne RS appelée COLS et cette colonne attend une ou plusieurs valeurs. 

&rp:COLS=1&rp:COLS=1&rp:COLS=5 etc..
0
Gerry