I have a DataSet with a query like this:
select s.name, w.week_ending, w.sales
from store s, weekly_sales_summary w
where s.id=w.store_id and s.id = ?
I created a more general solution, which handles optional/required parameters behaviour too. When parameter is not required and user doesn't select any value, the IN-clause gets disabled. It also allows the user to select both real values and null value.
In report initialize script I add this code:
/** Fullfill IN-clause in a data set query,
* using a List box report parameter.
* Placeholder must be the parentheses after IN keyword with wathever you want inside.
* If required is false then the whole IN-clause in the query
* must be surrounded by parentheses.
* dataType and required refers to the parameter, they must be passed,
* but should be better to find a way to retrieve them inside this function
* (given parameter name).
*/
function fulfillInClause(dataSet, placeholder, param, dataType, required) {
if (dataSet.queryText.indexOf(placeholder)>=0) {
var paramValue = params[param].value;
var emptyParam = (paramValue==null || paramValue.length<=0);
//build the list of possible values
// paramValue==null check in ternary operators
// will prevent exceptions when user doesn't select any value
// (it will not affect the query if param is optional,
// while we will never arrive here if it is required)
var replacement = " (";
if (dataType == "string")
replacement += (emptyParam ? "''" : createList(paramValue, ",", "'", "varchar(10)") );
else if (dataType == "integer")
replacement += (emptyParam ? "0" : createList(paramValue, ",", "" , "int" ) );
else
//TODO implement more cases
return;
replacement += ") ";
//if param is not required and user doesn't select any value for it
//then nullify the IN clause with an always-true clause
if (!required && emptyParam)
replacement += " or 0=0 ";
//put replacement in the query
dataSet.queryText = dataSet.queryText.replace( placeholder, replacement );
//DEBUG
params["debug" + dataSet.name + "Query"]=dataSet.queryText;
}
}
/** Create a string list of array values,
* separated by separator and each of them surrounded by a pair surrounders
*/
function createList(array, separator, surrounder, sqlDataType){
var result = "";
for(var i=0; i0)
result += separator;
if(array[i]!=null)
result += surrounder + array[i] + surrounder;
else
result += "cast(null as " + sqlDataType + ")";
}
return result;
}
In dataset query put your special IN-clause:
select F1, F2
from T1
where F3='Bubi'
and ( F4 in (''/*?customers*/) )
In beforeOpen script of the dataset with the IN-clause write:
fulfillInClause(this, "(''/*?customers*/)", "customers", "string", false);
Note that I used a placeholder which allows the query to run also before the replacement (eg. it has quotes as F4 is a varchar). You can build a placeholder that fits your case.