formulating an SSRS query to include zero/empty rows in a GROUP BY - sql-server

I'm working on a SSRS report and I'm having an issue with my Plant name not showing when there is no data available for the date range selected.
The far left column, first row (technically the 2nd by the image) is where my plant name should appear at all times:
Essentially the first image showed just my blank rows/columns. The first column, first row is where my plant name should be at all times. The remaining columns are my returned data based on date selection.
The second image would show everything working as it should when there is data.
I'm grouping by PlantCode in SSRS which is what gives my my plant name. I don't know how to get the plant name to appear even if there is not data available.
Is this possible?
I THOUGHT I could use something like iif(salesvolume is NOTHING, [PlantCODE],[PlantCode])
Here is the database query for the report
SELECT
PInv.[Plant_Numer],
PInv.[Plant_Code],
PInv.{Department_number],
PInv.[Inventory_Volume],
Pinv.[Inventory_Date], -- 'Last Inventory Date'
pls.[Actual_Volume],
pls.[Budget_Volume],
ppf.[Good_Output_Product_Units] AS 'Production Volume', -- 'Next Day Production
CASE
WHEN coalesce (pls.[Acutal_Volume],0) = 0 and coalesce (pls.[Actual_Sales_Dollars],0) = 0 THEN 0
ELSE ((pls.[Actual_Sales_Dollars/pls.[Actual_Volume])) AS 'Average Price' -- 'Next Day Sales'
FROM
[TrueOpportunity].[dbo].[Production_Fact] pf
inner join [TrueOpportunity].[dbo].[Production_Process_Fact] ppf on ppf.production_number = pf.production_number
inner join [TrueOpportunity].[dbo].[Process] prc on prc.process_number = pf.process_number
inner join [TrueOpportunity].[dbo].[Department] dpt on dpt.department_number = prc.department_number
inner join [WoodProduction_New].[dbo].[Plywood_Layup_Sales] pls on pls.procesS_number = pf.procesS_number
inner join [WoodProduction_New].[dbo].[Process_Inventory] Pinv on PInv.[Inventory_Date] = pf.date
and pls.product_date = pf.date
and dpt.department_number = pinv.department_number
WHERE
pf.date between #BeginningDate and #EndingDate

I think you want to change your query so that Process Inventory is your primary table and all other tables are LEFT JOINED to that table. That way the Plant Number & Code will show up regardless of whether there is matching data in the other tables.
This syntax is probably not completely correct, but I would start out by changing your FROM clause to look something like this:
FROM
[WoodProduction_New].[dbo].[Process_Inventory] Pinv
LEFT JOIN [TrueOpportunity].[dbo].[Production_Fact] pf
ON PInv.[Inventory_Date] = pf.date
LEFT JOIN [TrueOpportunity].[dbo].[Production_Process_Fact] ppf
ON ppf.production_number = pf.production_number
LEFT JOIN [TrueOpportunity].[dbo].[Process] prc
ON prc.process_number = pf.process_number
LEFT JOIN [TrueOpportunity].[dbo].[Department] dpt
ON dpt.department_number = prc.department_number
AND dpt.department_number = pinv.department_number
LEFT JOIN [WoodProduction_New].[dbo].[Plywood_Layup_Sales] pls
ON pls.process_number = pf.process_number
AND pls.product_date = pf.date
Experiment with that and see if you can get it to display the data that you want.

Related

T-SQL right outer join doesn't seem to work

I am having trouble with a right join that doesn't seem to be doing what I want.
The query below doesn't bring back all of the records from the grp table. I'm expecting a few rows matching the 30555 gl record and 30 rows from the grp table with nulls for the gl columns. Instead I get the expected few rows for the 30555 gl record and only 3 matching grp rows instead of the 30.
select gl.Tran_Number, gl.Amount, gl.Cost_Center, ' - ' as blank, grp.*
from GL_DETAIL_MC gl
right outer join EM_COST_GROUP_LIST_MC grp on grp.Cost_Center_Code = gl.Cost_Center and grp.Company_Code = gl.Company_Code
where
(gl.Company_Code = 'RCL' or grp.Company_Code = 'RCL')
and (gl.Tran_Number = '30555 ' or gl.Transaction_ID is null)
Not really sure where I've gone wrong here. Oh and I should mention that I tried creating a similar table structure in a test database and everything works as I expected. This leads me to thing that there is a database setting that is changing how the query is returning results.
The outer join is fine. The problem is the where clause.
I presume you intend:
select gl.Tran_Number, gl.Amount, gl.Cost_Center, ' - ' as blank, grp.*
from EM_COST_GROUP_LIST_MC grp LEFT JOIN
GL_DETAIL_MC gl
on grp.Cost_Center_Code = gl.Cost_Center and
grp.Company_Code = gl.Company_Code and
gl.Company_Code = 'RCL' and
gl.Tran_Number = '30555
where grp.Company_Code = 'RCL' or gl.Company_Code is not null;
I much prefer left join to right join.

SQL server -Multiple address joins in from clause

Ok, so I might be trying to do this all wrong, but here it goes.
In my data I have customer seq which is where the order was shipped to. But, since some orders are dropped shipped they have a different customer number and seq kept in a different table.
So basically, I want to say
if custaddr.country <> "" then custaddr.country, else DR.country
the from clause I currently have looks like this
CO is order table
Coitem is line of order
co_ship is shipped line
custaddr is customer address
if the order is drop ship, the customer and seq is pulled from coitem instead of co.
from
co inner join coitem on co.co_num = coitem.co_num
inner join co_ship on (co_ship.co_num = coitem.co_num and co_ship.co_line = coitem.co_line and co_ship.co_release = coitem.co_release)
inner join custaddr on (co.cust_num = custaddr.cust_num and co.cust_seq = custaddr.cust_seq)
inner join custaddr DR on (coitem.cust_num = custaddr.cust_num and coitem.cust_seq = custaddr.cust_seq)
when I run this, with the last inner join active I get no results.

Why do I have duplicate records in my JOIN

I am retrieving data from table ProductionReportMetrics where I have column NetRate_QuoteID. Then to that result set I need to get Description column.
And in order to get a Description column, I need to join 3 tables:
NetRate_Quote_Insur_Quote
NetRate_Quote_Insur_Quote_Locat
NetRate_Quote_Insur_Quote_Locat_Liabi
But after that my premium is completely off.
What am I doing wrong here?
SELECT QLL.Description,
QLL.ClassCode,
prm.NetRate_QuoteID,
QL.LocationID,
ISNULL(SUM(premium),0) AS NetWrittenPremium,
MONTH(prm.EffectiveDate) AS EffMonth
FROM ProductionReportMetrics prm
LEFT JOIN NetRate_Quote_Insur_Quote Q
ON prm.NetRate_QuoteID = Q.QuoteID
INNER JOIN NetRate_Quote_Insur_Quote_Locat QL
ON Q.QuoteID = QL.QuoteID
INNER JOIN NetRate_Quote_Insur_Quote_Locat_Liabi QLL
ON QL.LocationID = QLL.LocationID
WHERE YEAR(prm.EffectiveDate) = 2016 AND
CompanyLine = 'Ironshore Insurance Company'
GROUP BY MONTH(prm.EffectiveDate),
QLL.Description,
QLL.ClassCode,
prm.NetRate_QuoteID,
QL.LocationID
I think the problem in this table:
What Am I missing in this Query?
select
ClassCode,
QLL.Description,
sum(Premium)
from ProductionReportMetrics prm
LEFT JOIN NetRate_Quote_Insur_Quote Q ON prm.NetRate_QuoteID = Q.QuoteID
LEFT JOIN NetRate_Quote_Insur_Quote_Locat QL ON Q.QuoteID = QL.QuoteID
LEFT JOIN
(SELECT * FROM NetRate_Quote_Insur_Quote_Locat_Liabi nqI
JOIN ( SELECT LocationID, MAX(ClassCode)
FROM NetRate_Quote_Insur_Quote_Locat_Liabi GROUP BY LocationID ) nqA
ON nqA.LocationID = nqI.LocationID ) QLL ON QLL.LocationID = QL.LocationID
where Year(prm.EffectiveDate) = 2016 AND CompanyLine = 'Ironshore Insurance Company'
GROUP BY Q.QuoteID,QL.QuoteID,QL.LocationID
Now it says
Msg 8156, Level 16, State 1, Line 14
The column 'LocationID' was specified multiple times for 'QLL'.
It looks like DVT basically hit on the answer. The only reason you would get different amounts(i.e. duplicated rows) as a result of a join is that one of the joined tables is not a 1:1 relationship with the primary table.
I would suggest you do a quick check against those tables, looking for table counts.
--this should be your baseline count
SELECT COUNT(*)
FROM ProductionReportMetrics
GROUP BY MONTH(prm.EffectiveDate),
prm.NetRate_QuoteID
--this will be a check against the first joined table.
SELECT COUNT(*)
FROM NetRate_Quote_Insur_Quote Q
WHERE QuoteID IN
(SELECT NetRate_QuoteID
FROM ProductionReportMetrics
GROUP BY MONTH(prm.EffectiveDate),
prm.NetRate_QuoteID)
Basically you will want to do a similar check against each of your joined tables. If any of the joined tables are part of the grouping statement, make sure they are also in the grouping of the count check statement. Also make sure to alter the WHERE clause of the check count statement to use the join clause columns you were using.
Once you find a table that returns the incorrect number of rows, you will have your answer as to what table is causing the problem. Then you will just have to decide how to limit that table down to distinct rows(some type of aggregation).
This advice is really just to show you how to QA this particular query. Break it up into the smallest possible parts. In this case, we know that it is a join that is causing the problem, so take it one join at a time until you find the offender.

SQL query select geography point

I'm new in SQL querying and I need to get the last position of some players that are active, meaning they have Play value equal to 1. I have to make a join between the table Events where I have the players activity with columns:
ID: unique row id
Timestamp: time when the player changed his status for active to inactive or active again
PlayerId: id of the player that this event is for
Active: 1-Active, 0-Inactive
with the table Positions where I have all players position at every 2-3 seconds with columns:
PlayerId
Timestamp: time when the position was received
Location: a geography point with the received position
in order to get the current latitude and longitude of the players that are active.
My current query:
select
e.PlayerId, e.Active,
p.Location.Lat, p.Location.Long,
max_date = max(e.Timestamp),
max_date2 = max(p.Timestamp)
from
Events e
inner join
Positions p on e.PlayerId = p.PlayerId
where
e.Active= 1
group by
e.PlayerId, e.Active, p.Location.Lat, p.Location.Long
but instead of returning 2 rows I get much more. I guess it's because of the b.Location.Lat, b.Location.Long fields inside the group by clause because the simple query:
select
e.PlayerId, e.Active,
max_date = max(e.Timestamp),
max_date2 = max (p.Timestamp)
from
Events e
inner join
Positions p on e.PlayerId = p.PlayerId
where
e.Active = 1
group by
e.PlayerId, e.Active
returns the correct 2 rows but I need to also get the Lat-Long columns.
UPDATE
I found an issue inside my query. When I've run it again for different values I've seen that it returns all the players position if they were even only once active and after that they got inactive. But if the last value for Active (according to the maximum timestamp) for one user is 0, then the query should remove the player location from the response.
Is there any way that I can add those columns without getting more rows than needed?
You could wrap your current query in an outer query, then join to your positions table again. Something like this;
SELECT
base.PlayerId
,base.Active
,base.max_date
,base.max_date2
,p.Location.lat
,p.Location.long
FROM
(
SELECT a.PlayerId ,
a.Active,
max_date = max( a.Timestamp ),
max_date2 = max (b.Timestamp)
FROM Events a
INNER JOIN Positions b
ON a.PlayerId =b.PlayerId
WHERE a.Active= 1
GROUP BY a.PlayerId , a.Active
) base
JOIN Positions p
ON base.PlayerId = p.PlayerId
AND base.max_date2 = p.Timestamp
The reason your other query wasn't working is that you're going to have an entry for each lat & long point. Doing this will give you the unique list that you're after, then joins to Positions again to get lat long info.
Edit: As per the comments, if you want to exclude anybody with the latest Active value set to zero then add this to the end of the code;
JOIN
(
SELECT
e.PlayerID
,MAX(e.Timestamp) Timestamp
FROM Events e
GROUP BY e.PlayerID
) latest
ON base.PlayerID = latest.PlayerID
JOIN Events e2
ON latest.PlayerID = e2.PlayerID
AND latest.Timestamp = e2.Timestamp
WHERE e2.Active <> 0

When a SQL Server query returns no rows(NOT null rows) how do you include that in an aggregate function?

I'm writing a query to look for courses that do not have any of its gradable items graded.
In Blackboard when a user doesn't have a grade at all(e.g. no attempt was ever made) there simply isn't a row in the table gradebook_grade
So if a course doesn't have any grades at all the gradebook_grade table does not have any rows referencing the primary key of the Blackboard course_id
This is what I've used so far:
use bblearn
select cm.course_id
from course_main cm
join gradebook_main gbm on cm.pk1 = gbm.crsmain_pk1
join gradebook_grade gbg on gbm.pk1 = gbg.gradebook_main_pk1
where cm.pk1 = 3947
group by cm.course_id
having count(gbg.pk1) <= 0
The course in question(pk1 3947) is confirmed to not have any grades. So SQL Server says 0 rows affected, naturally.
The thing is, it doesn't select the course_id. I'm guessing having doesn't account for blank/non-existent rows. Is there a way to structure the query to get the course ID when there isn't anything returned? Am I joining on the wrong columns or using where on the wrong column? Any help is appreciated.
Use a left join
select cm.course_id
from course_main cm
left join gradebook_main gbm on cm.pk1 = gbm.crsmain_pk1
left join gradebook_grade gbg on gbm.pk1 = gbg.gradebook_main_pk1
where cm.pk1 = 3947
group by cm.course_id

Resources