I have a procedure that is supposed to build a report in SSRS with numbers for a list of people where column A is their name, column B and C are their numbers thus far this year (from January and up to for example May), and column D and E are the same numbers from the previous year in the same span of months. Below is what the procedure looks like. Also; I've altered the names and key data here to make it more understandable for you, but that might mean that there is a slight typo here and there that I don't immediately spot. Examples of what the parameter data may be are put as a commented out line below each parameter.
ALTER PROCEDURE [dbo].[number_comparison]
@resource AS int
-- retrieves a specific employee, or NULL. NULL on this parameter will retrieve a list of all employees (or all within a given type if the employee_type parameter is set)
,@employee_Type AS nvarchar(20)
-- type will retrieve all employees of a certain type. NULL on this will retrieve all employees regardless of type
,@time AS nvarchar(6)
-- Comes in the form YYYYMM. Cannot be NULL.
AS
BEGIN
DECLARE @time_last_year nvarchar(6) = CONVERT(nvarchar(6), @time-100);
SELECT
fk_resource
,SUM(amount) AS sum_amount_last_year
,AVG(amount) AS avg_amount_last_year
INTO
#lastyearsnumbers
FROM
datamart.numbers_month
INNER JOIN
dvh.resources
ON
(resources.pk_resource = fk_resource)
AND
(resources.pk_ressurs != -1)
WHERE
(fk_time LIKE LEFT(@time_last_year,4)+'%')
AND
(@resource IS NULL OR fk_resource = @resource)
AND
(@employee_Type IS NULL OR employee_Type = @employeeType)
AND
(fk_time < ((@time_last_year)+1))
GROUP BY
fk_resource
SELECT
fk_resource
,name
,SUM(amount) AS sum_amount_this_year
,AVG(amount) AS avg_amount_this_year
,TEMP.sum_amount_last_year
,TEMP.avg_amount_last_year
FROM
datamart.numbers_month
INNER JOIN
dvh.resource
ON
(resource.pk_resource = fk_resource)
AND
(resource.pk_resource != -1)
LEFT OUTER JOIN
#lastyearsnumbers TEMP
ON TEMP.fk_resource = datamart.numbers_month.fk_resource
WHERE
(fk_time LIKE (LEFT(@time,4))+'%')
AND
(@resource IS NULL OR fk_resource = @resource)
AND
(@employee_Type IS NULL OR employee_Type = @employee_Type)
AND
(fk_time < (@time+1))
GROUP BY
fk_resource, name, TEMP.sum_amount_last_year, TEMP.avg_amount_last_year
END;
The point of this task is that it should be possible to retrieve a report for a given month of a year and see what the accumulated numbers from january of that year and up to the selected month is, and compare it to the same period from the year before.
It uses a Left Outer Join because some employees are new and do not have any numbers from last year.
When I execute this procedure in SQL Server Management Studio, it runs completely fine. I get all the right data and a list of employees that also include the new employees that have no data for last year.
When I execute the procedure in SSRS, I get a list of employees that only cover the employees that have data both for this year as well as last year. It is almost as if the left outer join is run as an inner join.
What could cause this?
I remember reading it somewhere (can't remember on top of my head), Report Wizard doesn't like temp tables. I will update the comment when I get it. But, in the mean time, can you try running the same query by using CTE (common table expression) instead of temp tables or using any staging tables?
I amended your script to use CTE, as below.
ALTER PROCEDURE [dbo].[number_comparison]
@resource AS int
-- retrieves a specific employee, or NULL. NULL on this parameter will retrieve a list of all employees (or all within a given type if the employee_type parameter is set)
,@employee_Type AS nvarchar(20)
-- type will retrieve all employees of a certain type. NULL on this will retrieve all employees regardless of type
,@time AS nvarchar(6)
-- Comes in the form YYYYMM. Cannot be NULL.
AS
BEGIN
DECLARE @time_last_year nvarchar(6) = CONVERT(nvarchar(6), @time-100);
WITH cte AS
(
SELECT
fk_resource
,SUM(amount) AS sum_amount_last_year
,AVG(amount) AS avg_amount_last_year
FROM
datamart.numbers_month
INNER JOIN
dvh.resources
ON
(resources.pk_resource = fk_resource)
AND
(resources.pk_ressurs != -1)
WHERE
(fk_time LIKE LEFT(@time_last_year,4)+'%')
AND
(@resource IS NULL OR fk_resource = @resource)
AND
(@employee_Type IS NULL OR employee_Type = @employeeType)
AND
(fk_time < ((@time_last_year)+1))
GROUP BY
fk_resource
)
SELECT
fk_resource
,name
,SUM(amount) AS sum_amount_this_year
,AVG(amount) AS avg_amount_this_year
,TEMP.sum_amount_last_year
,TEMP.avg_amount_last_year
FROM
datamart.numbers_month
INNER JOIN
dvh.resource
ON
(resource.pk_resource = fk_resource)
AND
(resource.pk_resource != -1)
LEFT OUTER JOIN
cte as TEMP
ON TEMP.fk_resource = datamart.numbers_month.fk_resource
WHERE
(fk_time LIKE (LEFT(@time,4))+'%')
AND
(@resource IS NULL OR fk_resource = @resource)
AND
(@employee_Type IS NULL OR employee_Type = @employee_Type)
AND
(fk_time < (@time+1))
GROUP BY
fk_resource, name, TEMP.sum_amount_last_year, TEMP.avg_amount_last_year
END;
Thanks to @vercelli for pointing out that I hadn't specified exactly which tables the group by parameters pointed to. SQL Server Management Studio natively understood which tables where the right one, but when run through SSRS this seemed to get screwed up. I gave the tables alias names and specified the tables on the parameters using the aliases and that seemed to solve the problem.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.