SSRS Sql query with when clause and input parameter - sql

I'm trying to get a SQL query working in SSRS.
This query is executed when I execute my report in SSRS. It is a select which simply populates my dataset.
I want to have the Date at the moment of the report execution on first execution and then I want the user to be able to input a different date if needed thus the need for the parameter.
Here it is :
Select contrat from contrats ctr,
INNER JOIN structure rs ON rs.id = ctr.id
INNER JOIN structure_members rsm ON rsm.id_structure = rs.id_structure
where
(((Date(ctr.date) = CASE WHEN ? IS NULL THEN Date(Now) END) or
(Date(rs.endDate) = CASE WHEN ? IS NULL THEN Date(Now) END)
GROUP BY crt.contrat
Don't mind any syntax error, I just simplified my query to get to the point : is this possible?
Can I do a case when end like this?
`CASE WHEN ? IS NULL THEN Date(Now)`
The ? is a date that I input such as 2014-08-04. The value could be null if I wanted to. That's why I'm trying to check if it is null then complete the query using Date(now) instead.
Thanks for your help.

Try this:
Select contrat from contrats ctr
INNER JOIN structure rs ON rs.id = ctr.id
INNER JOIN structure_members rsm ON rsm.id_structure = rs.id_structure
where
Date(ctr.date) = ISNULL(?,Today())
or
Date(rs.enddate) = ISNULL(?,Today())
GROUP BY crt.contrat
The CASE statement can be replaced by using ISNULL to get a default value for null input and using it in the comparison. If parameter is non-null, you compare the parameter value, else you compare today's date.

Related

Allow mulitple values not working in SSRS

I have a report that uses a multi value parameter when ran in SQL pulls data without issue. When applied in a Stored Procedure and processed through SSRS with "Allow Multi Values" enabled when selecting multiple values the report returns no data. Like other users if I select a single value the report will return data.
I have done some homework and tried increasing my parameter value but this did not help either.
Please see below for my query. The parameter in question is the #material parameter.
With Zone as
(Select
name,
id
From datex_Footprint.LocationContainersView
Where
typename IN ('Zone', 'Area')
)
SELECT inv.projectId,
inv.projectName,
inv.materialLookupCode,
inv.materialDescription,
CASE
WHEN sn.id IS NULL
THEN inv.totalPackagedAmount
ELSE 1
END AS totalPackagedAmount,
inv.licensePlateLookupCode,
z.name WarehouseZone,
inv.locationName,
sn.id serialNumberId,
sn.lookupCode,
udf.SerialRef1,
udf.SerialRef2,
udf.SerialRef3,
udf.SerialRef4,
udf.SerialRef5
FROM datex_footprint.InventoryDetailedViewByLicensePlateLot inv
LEFT OUTER JOIN datex_footprint.SerialNumbers sn ON sn.lotId = inv.lotId
AND sn.licensePlateId = inv.licensePlateId
AND sn.archived = 'False'
LEFT OUTER JOIN datex_footprint.SerialNumbersUdfs udf ON udf.id = sn.id
INNER JOIN datex_footprint.LocationContainersView lcv ON lcv.id = inv.locationId
INNER JOIN datex_footprint.locationcontainers LC ON LC.id = lcv.id
INNER JOIN Zone z ON z.id = LC.parentid
WHERE inv.projectName IN(#projectName)
AND inv.materialLookupCode IN(#material)
AND (inv.locationName IN(#locationName)
OR (#locationName IS NULL));
If you don't have to use a stored procedure then the easiest way of solving this would be to put this code directly into your dataset. It will then work as you expect, SSRS will convert you multi-value parameter into a comma separated list and inject it into the SQL statement.
If you have to use the stored proc then you will need to do all the conversion yourself including splitting the values up inside your stored proc. There are plenty of examples out there on how to do this such as http://www.codeulike.com/2012/03/ssrs-multi-value-parameters-with-less.html
Personally, I always put dataset code directly in the dataset query, it's more convenient, means less objects on the SQL server but could be less secure.

SQL - select data based on one specific input value or all if no input value

I am trying to retrieve data using an input variable that is a Customer code. If a user enters the customer code, the query retrieves that customers data, but if the user leaves the customer code blank, I want to retrieve all customers data. Below is the code where I can retrieve data based on the customer code input in '3_customer' but I can't figure out how to do this IF-THEN-ELSE type of query I need to get data for all customers if the input variable is left blank.
Thanks,
Don
SELECT
open_item.order_id order_id,
convert(varchar(10),orders.ordered_date,101) order_date,
orders.revenue_code_id,
orders.operations_user,
open_item.customer_id cust_no,
customer.name cust_name,
convert(varchar(10),open_item.gl_date,101) adjust_date,
open_item.amount amount,
open_item.record_type type,
open_item.ar_reason_code_id,
ar_reason_code.descr reason
FROM
open_item
LEFT OUTER JOIN
customer ON customer.id = open_item.customer_id
LEFT OUTER JOIN
ar_reason_code ON open_item.ar_reason_code_id = ar_reason_code.id
LEFT OUTER JOIN
orders ON orders.id = open_item.order_id
WHERE
open_item.gl_date >= $1_sdate$ AND
open_item.gl_date <= $2_edate$ AND
open_item.source = 'C' AND
open_item.record_type = 'C' AND
open_item.customer_id = $3_customer$
An alternative approach is to:
open_item.customer_id = coalesce($3_customer$, open_item.customer_ID)
assuming $3_customer$ will be NULL
so $3_customer$ must not be null so then use a case
open_item.customer_id = case when $3_customer$ = ''
then open_item.customer_ID else $3_customer$
coalesce takes the first non-null value in a series in essence this will always return TRUE when the customer parameter is null. It does this because it compares the same values thus always equaling; otherwise this will filter for the specific $3_customer$ provided
You need to slightly change the WHERE clause for the customer condition from this:
and open_item.customer_id = $3_customer$
to something like this: (The below code comes with the assumption that $3_customer$ is getting inserted into the query string, and will be set to NULL if empty)
and ($3_customer$ IS NULL OR open_item.customer_id = $3_customer$)

sql update using select and sub select with joins

I have an update statement that I am using to change the value of my building field if certain criteria is met.
Here is where I tell it to set my building value to the result of my select statement
update Table set Building = (select case when child.date determined between child.entry date and child.withdrawal date
then child.building else child.[offender bldg]end
Then my select statement is then a product of another select statement where I have to define the value for date3 because it has nulls and I need it force it to be current date to ensure that I am capturing all the records that need to be updated.
from (select w.BUILDING, [Withdrawal Date] = case when WITHDRAWAL_DATE is null then GETDATE() else w.WITHDRAWAL_DATE end,a.DATE_DETERMINED,w.ENTRY_DATE,a.RESP_BUILDING,o.BUILDING[Offender Bldg]
from dbo._temp_disc_off a inner join dbo.offender o on (a.INCIDENT_ID = o.INCIDENT_ID) inner join dbo.entry w on (o.PERSON_ID = w.STUDENT_ID))child</b>
This next section is associated to the first select statement and filters for buildings that meet either criteria
where child.DATE_DETERMINED between child.ENTRY_DATE and child.[Withdrawal Date] and child.RESP_BUILDING is null
or child.DATE_DETERMINED between child.ENTRY_DATE and child.[Withdrawal Date] and child.RESP_BUILDING <> child.[Offender Bldg])</b>
I have to set it up this way, because I need to compare to a date and not a null value because my result set goes from 2425 to 461 if I don't set withdrawal date to getdate() if null.
When I run the query I get the following error:
Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.
I know that it is trying to return multiple values, and that is what I want. But when I try to use IN instead of = I get an incorrect syntax error.
The statement is not being used in a stored procedure, I am just trying to mass update some records. Please help, and please over look the fact that my syntax is a little off.
Thanks in advance
Updated My Question with Full Block
*here is my full statement in one block, I made some changes to it since posting, but I am trying to do the same update the temp disc off action table resp_building field. I can only do this if the date_determined is between the entry and withdrawal dates, but in some cases the withdrawal date is null, so I add a sub select where I provide a value for withdrawal date.
update dbo._temp_disc_off_action
set RESP_BUILDING = (
select case when child.DATE_DETERMINED between child.entry_date and child.[Withdrawal Date]
then child.BUILDING else child.[Offender Bldg] end
from (
select w.BUILDING, [Withdrawal Date] = case when WITHDRAWAL_DATE is null
then GETDATE()
else w.WITHDRAWAL_DATE end,
a.DATE_DETERMINED, w.ENTRY_DATE, a.RESP_BUILDING, o.BUILDING [Offender Bldg]
from dbo._temp_disc_off_action a
inner join dbo.DISC_OFFENDER o
on a.INCIDENT_ID = o.INCIDENT_ID
inner join dbo.REG_ENTRY_WITH w
on o.PERSON_ID = w.STUDENT_ID
where w.BUILDING = 41) child
where child.DATE_DETERMINED between child.ENTRY_DATE and child.[Withdrawal Date]
and child.RESP_BUILDING is null
or child.DATE_DETERMINED between child.ENTRY_DATE and child.[Withdrawal Date]
and child.RESP_BUILDING <> child.[Offender Bldg])
The problem is:
update Table set Building = (sub query).
What you are trying to do is update a single column, Building, with a single value returned from the sub query. However, your sub query is returning more than one value. So instead of Building 4, it gives you Building 4, 10, and 19. Sql Server can't set a single column to multiple values and throws the error.
The easiest way to debug is to convert your entire update statement into a select statement that selects the original value and the value you want to update to. You can examine the result select and see why you have duplicate rows from your sub select and figure out how to return a single value, or potentially concatenate or group multiple rows together to return a single value.
I figured it out, I was completely over complicating things and was able to update the fields I wanted by simply running a statement where I included CASE statement in my where clause. That allowed me check if the date determined is between the two dates, while replacing null values of my withdrawal date with current date. Here is my statement below:
UPDATE dbo._temp_disc_off_action SET RESP_BUILDING = w.BUILDING
FROM dbo._temp_disc_off_action a JOIN dbo.DISC_OFFENDER o ON (a.INCIDENT_ID = o.INCIDENT_ID) JOIN dbo.REG_ENTRY_WITH w ON (o.PERSON_ID = w.STUDENT_ID)
WHERE a.DATE_DETERMINED BETWEEN w.ENTRY_DATE AND CASE WHEN w.WITHDRAWAL_DATE IS NULL THEN GETDATE() ELSE w.WITHDRAWAL_DATE END AND a.RESP_BUILDING IS NULL AND **o.BUILDING = '41'
**OR a.DATE_DETERMINED BETWEEN w.ENTRY_DATE AND CASE WHEN ** w.WITHDRAWAL_DATE **IS NULL THEN GETDATE() ELSE w.WITHDRAWAL_DATE END
AND a.RESP_BUILDING <> o.BUILDING AND o.BUILDING = '41'

SQL Server: select only if nested select returns something

I am trying to set the following query so that it only selects any data from the DaysMov table (A) if the nested Select finds a matching date in the Calendar table (B).
Currently in such a case it just returns nothing for "dayMov" but still selects the other data from table A.
Can someone tell me how I can achieve this, e.g. by using Where or Case ?
SELECT
(
SELECT B.calendar_DT
FROM Calendar B
WHERE B.year_id = #selYear AND B.month_of_year = A.calMonth AND B.day_of_week = A.calDay AND (B.day_of_month BETWEEN A.calFrom AND A.calTill)
) AS dayMov,
A.countries,
A.regions,
'variable' AS validity,
A.name,
A.desc,
'' AS mode
FROM DaysMov A
WHERE A.mode = ''
Many thanks for any help with this, Tim.
You should be able to do the same thing with an inner join, like this:
SELECT
B.calendar_DT AS dayMov,
A.countries,
A.regions,
'variable' AS validity,
A.name,
A.desc,
'' AS mode
FROM DaysMov A
INNER JOIN Calendar B ON B.year_id = #selYear AND B.month_of_year = A.calMonth AND B.day_of_week = A.calDay AND (B.day_of_month BETWEEN A.calFrom AND A.calTill)
WHERE A.mode = ''
This query will not produce a row when Calendar does not have a match on the specified condition. Assuming that the query from your post has worked (except that it produced some rows that you did not want) the query above shouldn't produce additional rows, because the subquery on the same condition returned at most a single result.

Using Case Statement to replace value in one field based on value in a seperate field

I'm creating a report in SSRS and I can't use the IIF statement within the report to get the following done. I'm getting aggregate errors when I try to sum within the SSRS report.
`IIF(Fields!Period=0,0,IIF(Period=13,0,Balance/12))`
Works fine up until the moment I try to Sum.. get a silly aggregate error "Aggregate functions other than First, Last, Previous, Count, and Count Distinct can only aggregate data of a single data type"... These are all integers.
Basically I have a value in Master.Balance that I need to divide by 12 only when Secondary.Period equals 0 or 13. If Secondary.Period equals 0 or 13 then the value should be 0. I know my problem has to do with including the relationship between the tables, but I just don't know how to write that in.
Here is what I'm trying to use:
`CASE
WHEN Secondary.Period=0 OR Secondary.Period=13
THEN 0
ELSE Master.Balance/12
End As BudByPer`
Here is how the two tables are related to each other:
`FROM Master LEFT OUTER JOIN Secondary
ON Master.Project = Secondary.Project
AND Master.object = Secondary.object
AND Master.org = Secondary.org
`
How do I get the above into this:
SELECT DISTINCT Master.Project, Master.Object, Master.Fund, Master.Segment, Master.Balance, Secondary.project, Secondary.object, Secondary.org, Secondary.Period, Secondary.object, Secondary.Project.
FROM Master LEFT OUTER JOIN Secondary
ON Master.Project = Secondary.Project
AND Master.object = Secondary.object
AND Master.org = Secondary.org
WHERE (Master.object>=600000)
ORDER BY [Master.Fund]
You just need a select, it looks fine to me...
SELECT
Master.account,
Master.segment,
Secondary.desc,
Secondary.bud,
Segment.Num,
Segment.office,
CASE
WHEN Secondary.Period=0 OR Secondary.Period=13 THEN 0
ELSE Master.Balance/12
End As BudByPer
FROM Master
LEFT JOIN Secondary
ON Master.Project = Secondary.Project
AND Master.object = Secondary.object
AND Master.org = Secondary.org