Empty data in SSRS Reports - ssrs-2008

I'm working on ssrs reports. I was able to see the data or result of my stored procedure.unfortunatesly, when used the same as my dataset for report I was unable to see the data instead i'm getting 0 records.what might be the reasons ?My reports structure will be as like below image :
My current result :
Below is my procedure :
ALTER Proc [dbo].[SP_Get_CIPPSubjectMarks_New_HTSTEST] -
-7,'1,17,8','2537,2555,2558,2568'
(
#ReportId int=7,
#SubjectId varchar(200),
#SectionId varchar(200)
)
AS
BEGIN
Create table #temp (Name Varchar(500),Class varchar(50),Section
Varchar(20),enrollno varchar(500),SubjectName varchar(500),TermName
varchar(500),TestName varchar(500),TestGroupName varchar(500),Weightage
int,IsWeight bit,Marks varchar(20),MaxMarks int,IsAbsent bit,SubjectOrder
Varchar(200))
Insert into
#temp(Name,Class,Section,enrollNo,SubjectName,
TermName,TestName,TestGroupName,Weightage,IsWeight,Marks,
MaxMarks,IsAbsent,SubjectOrder)
SELECT DISTINCT CONCAT(d.name,' ',d.surname),cls.Value,sec.Value,
e.enroll_no,
CASE WHEN ISNULL(cxs.subject_alias,'')='' THEN CASE WHEN rtv.value='Second
Language' then '2ND LANGUAGE:' + b.Name WHEN
rtv.value='Third Language' THEN '3rd Language:'+b.name else b.name end
ELSE cxs.subject_alias end as SubjectName,
z.str_termname,c.str_termtestname,i.str_testgroupname,
i.str_testweightage,i.is_weighted_average,a.marks,max_marks,a.is_absent,
CASE WHEN rtv.value='Second Language' THEN 'Second Language' WHEN
rtv.Value='Third Language' THEN 'Third Language' When
ISNULL(cxs.subject_alias,'')='' THEN b.Name
ELSE cxs.subject_alias end as SubOrder
FROM marks_entry_HTS a JOIN subject b ON a.fk_subject_id=b.Id and a.marks
is not null
LEFT JOIN subjectCategory_HTS l ON l.Id= b.subject_categoryID
JOIN class_term_test_mapping_HTS c ON a.fk_class_term_test_mapping_id=c.id
-- added by me
JOIN class_term_test_category_HTS ctc on c.fk_termcategoryid = ctc.id
JOIN reference_type_value rtv ON rtv.id=a.fk_subject_type_id
-- close
JOIN Term_Test_Subject_AssessmentType_HTS m ON m.fk_term_testID=c.id and
m.fk_SubjectID=b.Id
JOIN class_report_types_mapping_test_HTS k ON
k.fk_class_term_test_mapping_id=c.Id
JOIN class_term_mapping_HTS z ON z.id=k.fk_class_term_mapping_id
JOIN Term_Test_Testgroup_aggregate_HTS i ON
i.Id=c.fk_testgroup_aggregateID
JOIN TestGroup_HTS j on j.Id=i.fk_TestGroupID
JOIN student d ON a.fk_student_id=d.Id JOIN student_enroll_no e ON
e.fk_student_id=d.id and IsNULL(e.is_deleted,0)=0
JOIN student_academic f on f.fk_student_enroll_no_id=e.id and
f.fk_academic_year_id=c.fk_academic_year_id
JOIN reference_type_value cls on cls.Id=f.fk_class_id
LEFT JOIN reference_type_value sec ON sec.Id=f.fk_section_id
LEFT JOIN max_marks_entry_HTS h on h.id=a.fk_max_marks_entry_id
join class_xref_subjects cxs ON h.fk_subject_id=cxs.fk_subject_id and
cxs.fk_subject_type_id=h.fk_subject_type_id and
IsNull(cxs.is_deleted,0)=0
and cxs.fk_class_id=h.fk_class_id and
cxs.fk_academic_year_campus_id=h.fk_academic_year_campus_id and
cxs.fk_curriculum_segment_id=h.fk_curriculum_segment_id
where k.fk_class_report_types_mapping_id=#ReportId
and h.fk_section_id in (select * from SplitStringByChar(#SectionId,','))
and a.fk_subject_id in (select * from SplitStringByChar(#SubjectId,','))
select Name,Class,Section,enrollNo,SubjectName,TermName,
TestGroupName as TestName,
Case WHEN IsWeight=1 THEN Round(Cast(((avg(CAST(Marks as
float)/cast(MaxMarks as float)))*Weightage) as decimal(10,0)),0)
else Round(Cast(((cast(max(Marks) as float)/cast(max(MaxMarks) as
float))*Weightage) as decimal(10,0)),0) ENd as Marks ,
SubjectOrder ,sum(maxmarks) as maxmarksare INTO #temp1 from #temp
GROUP BY Name,Class,Section,enrollNo,SubjectName,
TermName,SubjectOrder,IsWeight,Weightage,TestGroupName
Insert into #temp
(Name,Class,Section,enrollNo,SubjectName,
TermName,TestName,Marks,SubjectOrder)
select
Name,Class,Section,enrollNo,SubjectName,TermName,'Total',
SUM(Marks),SubjectOrder from #temp1
GROUP BY Name,Class,Section,enrollNo,SubjectName,TermName,SubjectOrder
Insert into #temp
(Name,Class,SubjectName,Section,enrollNo,TermName,TestName,Marks)
select Name,Class,'Total',Section,enrollNo,TermName,'Total
Marks',SUM(Marks)
from #temp1
GROUP BY Name,Class,Section,enrollNo,TermName
Insert into #temp
(Name,Class,SubjectName,Section,enrollNo,TermName,TestName,Marks)
select
Name,Class,'Total',Section,enrollNo,TermName,'Percentage',
SUM(Marks)*100/sum(m
axmarksare) from #temp1
GROUP BY Name,Class,Section,enrollNo,TermName
select *from #temp
drop table #temp
drop table #temp1
end
My procedure result is as like below image :

As there are a number of things that could be wrong I would do the following.
Create copy of your report
Remove the existing dataset and tablix if you want.
Create some new datasets that just get the basic data (e.g. SELECT top 10 * FROM marks_emtry_HTS). Do not use your parameters yet as we just want to test we can get basic data.
Add some tables to your report to show that the data is being returned
Add a dataset to test you are passing and parsing parameters correctly by using a dataset query like select * from SplitStringByChar(#SectionId,',') and then put tablix on your report to show the results.
Try trimming your parameter values SET #SectionId = LTRIM(RTRIM(#SectionId)) to make sure you're not handling leading or trailing space incorrectly in you split function.
If any parts do not work, run a trace on the SQL Server as you run the report and look at exactly what is being executed on the server.
I know a lot of those steps you will think might be unnecessary but take the time to do it and at least you are certain and you can exclude such basic checks from your investigation.

Related

SQL Server 2008 R2 query related to replacement of data

I have a scenario wherein I have to remove all the strings except a or b or c
My sample table is as follows:
Id Product
------------------
1. a,b,Da,c
2. Ty,a,b,c
3. a,sds,b
Sample output
Id Product
----------------
1. a,b,c
2. a,b,c
3. a,b
My current version is Microsoft SQL Server 2008 R2
This should help you out. As I state in the comments, I make use of Jeff Moden's DelimitedSplit8k, as you're using an older version of SQL Server. if you were using 2016+, you would have access to STRING_SPLIT. I also normalise your data; as storing delimited data is almost always a bad idea.
CREATE TABLE #Sample (id int, Product varchar(20));
INSERT INTO #Sample
VALUES (1,'a,b,Da,c'),
(2,'Ty,a,b,c'),
(3,'a,sds,b');
GO
--The first problem you have is you're storing delimited data
--You really should be storing each item on a separate row.
--This is, however, quite easy to do. i'm going to use a different
--table, however, you can change this fairly easily for your
--needs.
CREATE TABLE #Sample2 (id int, Product varchar(2));
GO
--You can split the data out by using a Splitter.
--My personal preference is Jeff Moden's DelimitedSplit8K
--which I've linked to above.
INSERT INTO #Sample2 (id, Product)
SELECT id, Item AS Product
FROM #Sample S
CROSS APPLY dbo.DelimitedSplit8K(S.Product,',') DS
WHERE DS.Item IN ('a','b','c');
GO
--And hey presto! Your normalised data, and without the unwanted values
SELECT *
FROM #Sample2;
GO
DROP TABLE #Sample;
DROP TABLE #Sample2;
If you have to keep the delimited format, you can use STUFF and FOR XML PATH:
WITH Split AS(
SELECT id,
Item AS Product,
ItemNumber
FROM #Sample S
CROSS APPLY dbo.DelimitedSplit8K(S.Product,',') DS
WHERE DS.Item IN ('a','b','c'))
SELECT id,
STUFF((SELECT ',' + Product
FROM Split sq
WHERE sq.id = S.id
ORDER BY ItemNumber
FOR XML PATH('')),1,1,'')
FROM Split S
GROUP BY id;
This also will do the thing, using xml only:
select * into #t from (values('a,b,Da,c'),('Ty,a,b,c'),('a,sds,b'))v(Product)
;
with x as (
SELECT t.Product, st.sProduct
FROM #t t
cross apply (
SELECT CAST(N'<root><r>' + REPLACE(t.Product,',', N'</r><r>') + N'</r></root>' as xml) xProduct
)xt
cross apply (
select CAST(r.value('.','NVARCHAR(MAX)') as nvarchar) sProduct
from xt.xProduct.nodes(N'//root/r') AS RECORDS(r)
) st
where st.sProduct in ('a', 'b', 'c')
)
select distinct x.Product, REVERSE(SUBSTRING(REVERSE(cleared.cProduct), 2, 999)) cleared
from x
cross apply ( select (
select distinct ref.sProduct + ','
from x ref
where ref.Product = x.Product
for xml path('') )
)cleared(cProduct)
;
drop table #t

T-SQL how to join with one column a string and one an integer

How to join with one column a string and one an integer?
--PEOPLE_ID 000092437, PersonID 92437
select PC.PEOPLE_ID, Idn.PersonId,'Home Row 1', PC.Phone1 from #NextIdentityID Idn INNER JOIN PEOPLECHANGES PC on Idn.People_ID = PC.People_ID --PEOPLE_ID 000092437, PersonID 92437 one is varchar, one is integer
union all select PC.PEOPLE_ID, Idn.PersonId,'Office Row 2', PC.Phone2 from #NextIdentityID Idn INNER JOIN PEOPLECHANGES PC on Idn.People_ID = PC.People_ID
union all select PC.PEOPLE_ID, Idn.PersonId,'Cell Row 3', PC.Phone3 from #NextIdentityID Idn INNER JOIN PEOPLECHANGES PC on Idn.People_ID = PC.People_ID
To make sure your varchar() data doesn't raise any errors you should check to see if it can be converted into an integer. One way to do this is with a case statement in the where clause. If it is not convertible then your join won't work - but at least your query can still run with out error.
This example shows how you can avoid potential errors.
create table #tempa(id int, descr varchar(50));
create table #tempb(id varchar(10), descr varchar(50));
insert into #tempa(id,descr) values (1234,'Body getta body getta');
insert into #tempb(id,descr) values ('001234','sis boom ba - rah rah rah');
insert into #tempa(id,descr) values (5678,'Weagle Weagle War Damn Eagle');
insert into #tempb(id,descr) values ('0005678','Kickem in the butt Big blue');
insert into #tempa(id,descr) values (9012,'this wont have a match');
insert into #tempb(id,descr) values ('x0912','sis boom ba');
Select a.id as a_id, b.id as b_id
,a.descr as a_descr, b.descr as b_descr
from #tempa a
left join #tempb b
on a.id = case when isnumeric(b.id) = 1 then cast(b.id as int) else 0 end
-- this one will raise an error
Select a.id as a_id, b.id as b_id
,a.descr as a_descr, b.descr as b_descr
from #tempa a
left join #tempb b
on a.id = b.id
drop table #tempa;
drop table #tempb;
If you convert the one with leading zeros to an integer you will get equal values:
SELECT CONVERT(INT, '000092437') = 92437
However, this assumes that all of your varchar column can be convert to int.
If that's not the case then you have to write a function to go the other way and add leading zeros.

More Efficient Way to Join Three Tables Together in Postgres

I am attempting to link three tables together in postgres.
All three tables are generated from subqueries. The first table is linked to the second table by the variable call_sign as a FULL JOIN (because I want the superset of entries from both tables). The third table has an INNER JOIN with the second table also on call_sign (but theoretically could have been linked to the first table)
The query runs but is quite slow and I feel will become even slower as I add more data. I realize that there are certain things that I can do to speed things up - like not pulling unnecessary data in the subqueries and not converting text to numbers on the fly. But is there a better way to structure the JOINs between these three tables?
Any advice would be appreciated because I am a novice in postgres.
Here is the code:
select
(CASE
WHEN tmp1.frequency_assigned is NULL
THEN tmp2.lower_frequency
ELSE tmp1.frequency_assigned END) as master_frequency,
(CASE
WHEN tmp1.call_sign is NULL
THEN tmp2.call_sign
ELSE tmp1.call_sign END) as master_call_sign,
(CASE
WHEN tmp1.entity_type is NULL
THEN tmp2.entity_type
ELSE tmp1.entity_type END) as master_entity_type,
(CASE
WHEN tmp1.licensee_id is NULL
THEN tmp2.licensee_id
ELSE tmp1.licensee_id END) as master_licensee_id,
(CASE
WHEN tmp1.entity_name is NULL
THEN tmp2.entity_name
ELSE tmp1.entity_name END) as master_entity_name,
tmp3.market_name
FROM
(select cast(replace(frequency_assigned, ',','.') as decimal) AS frequency_assigned,
frequency_upper_band,
f.uls_file_number,
f.call_sign,
entity_type,
licensee_id,
entity_name
from combo_fr f INNER JOIN combo_en e
ON f.call_sign=e.call_sign
ORDER BY frequency_assigned DESC) tmp1
FULL JOIN
(select cast(replace(lower_frequency, ',','.') as decimal) AS lower_frequency,
upper_frequency,
e.uls_file_number,
mf.call_sign,
entity_type,
licensee_id,
entity_name
FROM market_mf mf INNER JOIN combo_en e
ON mf.call_sign=e.call_sign
ORDER BY lower_frequency DESC) tmp2
ON tmp1.call_sign=tmp2.call_sign
INNER JOIN
(select en.call_sign,
mk.market_name
FROM combo_mk mk
INNER JOIN combo_en en
ON mk.call_sign=en.call_sign) tmp3
ON tmp2.call_sign=tmp3.call_sign
ORDER BY master_frequency DESC;
you'll want to unwind those queries and do it all in one join, if you can. Soemthing like:
select <whatever you need>
from combo_fr f
JOIN combo_en e ON f.call_sign=e.call_sign
JOIN market_mf mf mf ON mf.call_sign=e.call_sign
JOIN combo_mk mk ON mk.call_sign=en.call_sign
I can't completely grok what you're doing, but some of the join clauses might have to become LEFT JOINs in order to deal with places where the call sign does or does not appear.
After creating indexes on call_sign for all four involved tables, try this:
WITH nodup AS (
SELECT call_sign FROM market_mf
EXCEPT SELECT call_sign FROM combo_fr
) SELECT
CAST(REPLACE(u.master_frequency_string, ',','.') AS DECIMAL)
AS master_frequency,
u.call_sign AS master_call_sign,
u.entity_type AS master_entity_type,
u.licensee_id AS master_licensee_id,
u.entity_name AS master_entity_name,
combo_mk.market_name
FROM (SELECT frequency_assigned AS master_frequency_string, call_sign,
entity_type, licensee_id, entity_name
FROM combo_fr
UNION ALL SELECT lower_frequency, call_sign,
entity_type, licensee_id, entity_name
FROM market_mf INNER JOIN nodup USING (call_sign)
) AS u
INNER JOIN combo_en USING (call_sign)
INNER JOIN combo_mk USING (call_sign)
ORDER BY 1 DESC;
I post this because this is the simplest way to understand what you need.
If there are no call_sign values which appear in both market_mf and
combo_fr, WITH nodup ... and INNER JOIN nodup ... can be omitted.
I am making the assumption that call_sign is unique in both combo_fr and market_mf ( = there are no two records in each table with the same value), even if there can be values which can appear in both tables.
It is very unfortunate that you order by a computed column, and that the computation is so silly. A certain optimization would be to convert the frequency strings once and for all in the table itself. The steps would be:
(1) add numeric frequncy columns to your tables (2) populate them with the values converted from the current text columns (3) convert new values directly into the new columns, by inputting them with a locale which has the desired decimal separator.

T-SQL Need help to optimize table value function

I need help to optmize the SQL logic in one of my functions. Please, note that I am not able to use store procedure.
Here is my table. It will be initialized using #MainTable that contains a lot of records.
DECLARE TABLE #ResultTable
(
ResultValue INT
)
These are tables that stores some parameters - they can be emty too.
DECLARE TABLE #ParameterOne (ParameterOne INT)
DECLARE TABLE #ParameterTwo (ParameterOne NVARCHAR(100))
...
DECLARE TABLE #ParameterN(ParameterN TINYINT)
Now, I need to join a lot of tables to my #MainTable in order to select from it only some of its records.
The selected records depend on the information stored in the parameters table.
So, my current solution is:
INSERT INTO ResultTable(ResultValue)
SELECT ResultValue
FROM MainTable M
INNER JOIN #MainOne MO
ON M.ID=MO.ID
....
INNER JOIN #MainN MN
ON M.IDN=MN.ID
WHERE (EXISTS (SELECT 1 FROM #ParameterOne WHERE ParameterOne=MO.ID) OR NOT EXISTS (SELECT 1 FROM #ParameterOne))
AND
...
AND
(EXISTS (SELECT 1 FROM #ParameterN WHERE ParameterN=MN.Name) OR NOT EXISTS (SELECT 1 FROM #ParameterN ))
So, the idea is to add the records only if they match the current criteria from the parameters tables.
Because I am not able to use procedure to build dynamic query I am using the WHERE clause with combinations of EXISTS and NOT EXISTS for each parameter table.
The problem is that it works slower when I am adding more and more parameters table. Is there an other way to do this without using a lot of IF/ELSE statements checking what parameter table has records - it will make the function a lot bigger and difficult for read.
And ideas and advices are welcomed.
Good question.
Try the following one:
INSERT INTO ResultTable(ResultValue)
SELECT ResultValue
FROM MainTable M
INNER JOIN (SELECT * FROM #MainOne WHERE (EXISTS (SELECT 1 FROM #ParameterOne WHERE ParameterOne=#MainOne.ID) OR NOT EXISTS (SELECT 1 FROM #ParameterOne))) MO
ON M.ID=MO.ID
....
INNER JOIN (SELECT * FROM #MainN WHERE (EXISTS (SELECT 1 FROM #ParameterN WHERE ParameterOne=#MainN.Name OR NOT EXISTS (SELECT 1 FROM #ParameterN))) MO
ON M.IDN=MN.ID
Advantages:
Result of the JOIN is more quickly, because it does not process all data (it is already filtered)
It looks more simple for adjusting

How to design a SQL recursive query?

How would I redesign the below query so that it will recursively loop through entire tree to return all descendants from root to leaves? (I'm using SSMS 2008). We have a President at the root. under him are the VPs, then upper management, etc., on down the line. I need to return the names and titles of each. But this query shouldn't be hard-coded; I need to be able to run this for any selected employee, not just the president. This query below is the hard-coded approach.
select P.staff_name [Level1],
P.job_title [Level1 Title],
Q.license_number [License 1],
E.staff_name [Level2],
E.job_title [Level2 Title],
G.staff_name [Level3],
G.job_title [Level3 Title]
from staff_view A
left join staff_site_link_expanded_view P on P.people_id = A.people_id
left join staff_site_link_expanded_view E on E.people_id = C.people_id
left join staff_site_link_expanded_view G on G.people_id = F.people_id
left join facility_view Q on Q.group_profile_id = P.group_profile_id
Thank you, this was most closely matching what I needed. Here is my CTE query below:
with Employee_Hierarchy (staff_name, job_title, id_number, billing_staff_credentials_code, site_name, group_profile_id, license_number, region_description, people_id)
as
(
select C.staff_name, C.job_title, C.id_number, C.billing_staff_credentials_code, C.site_name, C.group_profile_id, Q.license_number, R.region_description, A.people_id
from staff_view A
left join staff_site_link_expanded_view C on C.people_id = A.people_id
left join facility_view Q on Q.group_profile_id = C.group_profile_id
left join regions R on R.regions_id = Q.regions_id
where A.last_name = 'kromer'
)
select C.staff_name, C.job_title, C.id_number, C.billing_staff_credentials_code, C.site_name, C.group_profile_id, Q.license_number, R.region_description, A.people_id
from staff_view A
left join staff_site_link_expanded_view C on C.people_id = A.people_id
left join facility_view Q on Q.group_profile_id = C.group_profile_id
left join regions R on R.regions_id = Q.regions_id
WHERE C.STAFF_NAME IS NOT NULL
GROUP BY C.STAFF_NAME, C.job_title, C.id_number, C.billing_staff_credentials_code, C.site_name, C.group_profile_id, Q.license_number, R.region_description, A.people_id
ORDER BY C.STAFF_NAME
But I am wondering what is the purpose of the "Employee_Hierarchy"? When I replaced "staff_view" in the outer query with "Employee_Hierarchy", it only returned one record = "Kromer". So when/where can we use "Employee_Hierarchy"?
See:
SQL Server - Simple example of a recursive CTE
MSDN: Recursive Queries using Common Table Expression
SQL Server recursive CTE (this seems pretty much like exactly what you are working on!)
Update:
A proper recursive CTE consist of basically three things:
an anchor SELECT to begin with; that can select e.g. the root level employees (where the Reports_To is NULL), or it can select any arbitrary employee that you define, e.g. by a parameter
a UNION ALL
a recursive SELECT statement that selects from the same, typically self-referencing table and joins with the recursive CTE being currently built up
This gives you the ability to recursively build up a result set that you can then select from.
If you look at the Northwind sample database, it has a table called Employees which is self-referencing: Employees.ReportsTo --> Employees.EmployeeID defines who reports to whom.
Your CTE would look something like this:
;WITH RecursiveCTE AS
(
-- anchor query; get the CEO
SELECT EmployeeID, FirstName, LastName, Title, 1 AS 'Level', ReportsTo
FROM dbo.Employees
WHERE ReportsTo IS NULL
UNION ALL
-- recursive part; select next Employees that have ReportsTo -> cte.EmployeeID
SELECT
e.EmployeeID, e.FirstName, e.LastName, e.Title,
cte.Level + 1 AS 'Level', e.ReportsTo
FROM
dbo.Employees e
INNER JOIN
RecursiveCTE cte ON e.ReportsTo = cte.EmployeeID
)
SELECT *
FROM RecursiveCTE
ORDER BY Level, LastName
I don't know if you can translate your sample to a proper recursive CTE - but that's basically the gist of it: anchor query, UNION ALL, recursive query