Several inner joins producing too many rows - sql-server-2005

I'm working on a field trip request software for school districts.
Each field trip has an account attached to it that will be billed. It will also have one or more driver/vehicle combinations and mileage and driver rates associated with each driver/vehicle combination.
I'm working on an accounting report that will show, by account, a count of the trips that are assigned to that account, the total number of miles driven on that account times a certain charge basis, and a total number of hours each driver has driven on that trip multiplied by their payrate.
I have a field trip (tripid=1) with two vehicles and two drivers and I expect two rows of output. However, I am getting 4 rows; Two rows for vehicle 81 and two rows for vehicle 56. Is there something in my joins that's causing too many rows to be outputted?
What's weird is Mister Driver is on both vehicles in the output of my query and so is Generic Person.
select distinct
tdv.tripid as tripid,
ta.name as account,
cb.chargebasisname as trip_type,
cb.defaultdistancerate as distance_rate,
(tc.odometerreturn-tc.odometerstart) as total_miles,
datediff(hour, tc.actualoriginstarttime,tc.actualoriginreturntime) as total_hours,
v.vehicle,
pr.hourlyrate as driver_rate,
e.firstname+' '+e.lastname as driver
from trip_tripdrivervehicle tdv
join trip_tripinformation ti
on ti.recordid = tdv.tripid
join trip_transportationaccounts ta
on ta.recordid = ti.accountid
join trip_invoicechargebasis cb
on cb.recordid = ta.defaultchargebasisid
join trip_tripcompletion tc
on tc.tripid = ti.recordid
join vehicles v
on v.recordid = tc.vehicleid
join trip_employeejobcategorypayrate pr
on pr.employeeid = tdv.driverid
join employees e
on e.recordid = tdv.driverid
where ti.triprequeststatusid = 7 and ti.recordid = 1
Here is my output:
https://lh6.googleusercontent.com/_Bbr20KcwLyw/TX5cwDhr7BI/AAAAAAAAbYE/qCfQtk6Xmeg/s800/sql_results.jpg

Looks like you also have two matches for the JOIN with table trip_tripcompletion - one that gives rows with total miles of 10 and another that gives rows with total miles of 50.
So each driver shows up with each total_miles option.
The JOIN condition for this table may need to be changed, or you can use GROUP BY along with MAX/MIN to show only the shortest/longest trip (depending on the need).

Related

SQL script of joining multiple tables shows duplicated record

The McLean family is challenging their total condo fees. Retrieve all invoice data related to condo fees (including details) for the McLean family for invoice 20065.  Selecting appropriate data to calculate the total condo fees for invoice number 20065. 
Tips: guest# is 'G5'.
startdate is '2019-08-03'
And they stayed in the condo for a week.
I write a script. But always shows duplicated output (two duplicated records). How can I do this without using the keyword "distinct"?
The expected output only shows one row of record.
select i.inv#, i.condo#, i.guest#, g.rlname, cs.startdate, cs.enddate, c.WeeklyFee
from guests g join reservations r
on g.guest# = r.guest#
join invoicedetails id
on r.rid = id.rid
join invoice i
on id.inv# = i.inv#
join condostays cs
on i.guest# = cs.guest# and i.condo# = cs.condo#
join condos c
on cs.condo# = c.condo#
where i.guest# = 'g5'
and i.inv# in (20065)
and startdate = '2019-08-03';
My output of showing duplicated records
Schema:
ERD:
Expected output (only one row of record output):

SQL Inner Join Combining Rows in Results - Too Few Results

I'm trying to create a report from four tables: Master, Details, Labor, Costs. Currently I have a working report pulling columns from Jobs, Details, and Costs. Shared key for all tables is JobNumber. I'm looking to get a sum of the costs and a sum of the hours for each job. Here is my code that works with three tables:
SELECT
JC_JobMaster.JobNumber,
JC_JobMaster.JobDescription1 AS Customer_Name,
JC_JobMaster.JobDescription2 AS Work,
JC_JobSortCategories.SortCategory2 AS Work_Type,
JC_JobMaster.CustomerCode,
JC_JobMaster.ContractValue,
SUM(JC_JobBalancesCostDollars.CurrentPeriodAmount*-1) AS Gross_profit,
JC_JobSortCategories.SortCategory1 AS City,
JC_JobSortCategories.SortCategory4 AS Salesman
FROM
JC_JobMaster INNER JOIN
JC_JobSortCategories ON JC_JobMaster.JobNumber = JC_JobSortCategories.JobNumber INNER JOIN
JC_JobBalancesCostDollars ON JC_JobMaster.JobNumber = JC_JobBalancesCostDollars.JobNumber
WHERE
JC_JobMaster.JobNumber between '11566' and '13441' and
JC_JobSortCategories.SortCategory5 = 'AWARDED' and
JC_JobSortCategories.SortCategory2 = 'FPR' and
JC_JobSortCategories.SortCategory1 in ('1')
Group By
JC_JobMaster.JobNumber,
JC_JobMaster.JobDescription1,
JC_JobMaster.JobDescription2,
JC_JobSortCategories.SortCategory2,
JC_JobMaster.CustomerCode,
JC_JobMaster.ContractValue,
JC_JobSortCategories.SortCategory1,
JC_JobSortCategories.SortCategory4
Order by
JC_JobMaster.JobNumber
Everything works fine - this query returns 45 rows with easily-verified data. However, adding in a fourth table using an inner join INNER JOIN JC_JobCostDetailLabourHours ON JC_JobMaster.JobNumber = JC_JobCostDetailLabourHours.JobNumber only returns 7 rows, and the summed column Gross_profit is incorrect. Using a LEFT JOIN as opposed to INNER JOIN gives me the proper 45 rows, but the summed column is still incorrect. The LabourHours and BalancesCostDollars tables have multiple entries for each job number that I'm wanting summed. What am I doing wrong with adding the fourth table, or did I just happen to get the right result by accident with the first summed column?

Sql Left or Right Join One To Many Pagination

I have one main table and join other tables via left outer or right outer outer join.One row of main table have over 30 row in join query as result. And I try pagination. But the problem is I can not know how many rows will it return for one main table row result.
Example :
Main table first row result is in my query 40 rows.
Main table second row result is 120 row.
Problem(Question) UPDATE:
For pagination I need give the pagesize the count of select result. But I can not know the right count for my select result. Example I give page no 1 and pagesize 50, because of this I cant get the right result.I need give the right pagesize for my main table top 10 result. Maybe for top 10 row will the result row count 200 but my page size is 50 this is the problem.
I am using Sql 2014. I need it for my ASP.NET project but is not important.
Sample UPDATE :
it is like searching an hotel for booking. Your main table is hotel table. And the another things are (mediatable)images, (mediatable)videos, (placetable)location and maybe (commenttable)comments they are more than one rows and have one to many relationship for the hotel. For one hotel the result will like 100, 50 or 10 rows for this all info. And I am trying to paginate this hotels result. I need get always 20 or 30 or 50 hotels for performance in my project.
Sample Query UPDATE :
SELECT
*
FROM
KisiselCoach KC
JOIN WorkPlace WP
ON KC.KisiselCoachId = WP.WorkPlaceOwnerId
JOIN Album A
ON KC.KisiselCoachId = A.AlbumId
JOIN Media M
ON A.AlbumId = M.AlbumId
LEFT JOIN Rating R
ON KC.KisiselCoachId = R.OylananId
JOIN FrUser Fr
ON KC.CoachId = Fr.UserId
JOIN UserJob UJ
ON KC.KisiselCoachId = UJ.UserJobOwnerId
JOIN Job J
ON UJ.JobId = J.JobId
JOIN UserExpertise UserEx
ON KC.KisiselCoachId = UserEx.UserExpertiseOwnerId
JOIN Expertise Ex
ON UserEx.ExpertiseId = Ex.ExpertiseId
Hotel Table :
HotelId HotelName
1 Barcelona
2 Berlin
Media Table :
MediaID MediaUrl HotelId
1 www.xxx.com 1
2 www.xxx.com 1
3 www.xxx.com 1
4 www.xxx.com 1
Location Table :
LocationId Adress HotelId
1 xyz, Berlin 1
2 xyz, Nice 1
3 xyz, Sevilla 1
4 xyz, Barcelona 1
Comment Table :
CommentId Comment HotelId
1 you are cool 1
2 you are great 1
3 you are bad 1
4 hmm you are okey 1
This is only sample! I have 9999999 hotels in my database. Imagine a hotel maybe it has 100 images maybe zero. I can not know this. And I need get 20 hotels in my result(pagination). But 20 hotels means 1000 rows maybe or 100 rows.
First, your query is poorly written for readability flow / relationship of tables. I have updated and indented to try and show how/where tables related in hierarchical relativity.
You also want to paginate, lets get back to that. Are you intending to show every record as a possible item, or did you intend to show a "parent" level set of data... Ex so you have only one instance per Media, Per User, or whatever, then once that entry is selected you would show details for that one entity? if so, I would do a query of DISTINCT at the top-level, or at least grab the few columns with a count(*) of child records it has to show at the next level.
Also, mixing inner, left and right joins can be confusing. Typically a right-join means you want the records from the right-table of the join. Could this be rewritten to have all required tables to the left, and non-required being left-join TO the secondary table?
Clarification of all these relationships would definitely help along with the context you are trying to get out of the pagination. I'll check for comments, but if lengthy, I would edit your original post question with additional details vs a long comment.
Here is my SOMEWHAT clarified query rewritten to what I THINK the relationships are within your database. Notice my indentations showing where table A -> B -> C -> D for readability. All of these are (INNER) JOINs indicating they all must have a match between all respective tables. If some things are NOT always there, they would be changed to LEFT JOINs
SELECT
*
FROM
KisiselCoach KC
JOIN WorkPlace WP
ON KC.KisiselCoachId = WP.WorkPlaceOwnerId
JOIN Album A
ON KC.KisiselCoachId = A.AlbumId
JOIN Media M
ON A.AlbumId = M.AlbumId
LEFT JOIN Rating R
ON KC.KisiselCoachId = R.OylananId
JOIN FrUser Fr
ON KC.CoachId = Fr.UserId
JOIN UserJob UJ
ON KC.KisiselCoachId = UJ.UserJobOwnerId
JOIN Job J
ON UJ.JobId = J.JobId
JOIN UserExpertise UserEx
ON KC.KisiselCoachId = UserEx.UserExpertiseOwnerId
JOIN Expertise Ex
ON UserEx.ExpertiseId = Ex.ExpertiseId
Readability of a query is a BIG help for yourself, and/or anyone assisting or following you. By not having the "on" clauses near the corresponding joins can be very confusing to follow.
Also, which is your PRIMARY table where the rest are lookup reference tables.
ADDITION PER COMMENT
Ok, so I updated a query which appears to have no context to the sample data and what you want in your post. That said, I would start with a list of hotels only and a count(*) of things per hotel so you can give SOME indication of how much stuff you have in detail. Something like
select
H.HotelID,
H.HotelName,
coalesce( MedSum.recs, 0 ) as MediaItems,
coalesce( LocSum.recs, 0 ) as NumberOfLocations,
coalesce( ComSum.recs, 0 ) as NumberOfLocations
from
Hotel H
LEFT JOIN
( select M.HotelID,
count(*) recs
from Media M
group by M.HotelID ) MedSum
on H.HotelID = MedSum.HotelID
LEFT JOIN
( select L.HotelID,
count(*) recs
from Location L
group by L.HotelID ) LocSum
on H.HotelID = LocSum.HotelID
LEFT JOIN
( select C.HotelID,
count(*) recs
from Comment C
group by C.HotelID ) ComSum
on H.HotelID = ComSum.HotelID
order by
H.HotelName
--- apply any limit per pagination
Now this will return every hotel at a top-level and the total count of things per the hotel per the individual counts which may or not exist hence each sub-check is a LEFT-JOIN. Expose a page of 20 different hotels. Now, as soon as one person picks a single hotel, you can then drill-into the locations, media and comments per that one hotel.
Now, although this COULD work, having to do these counts on an every-time query might get very time consuming. You might want to add counter columns to your main hotel table representing such counts as being performed here. Then, via some nightly process, you could re-update the counts ONCE to get them primed across all history, then update counts only for those hotels that have new activity since entered the date prior. Not like you are going to have 1,000,000 posts of new images, new locations, new comments in a day, but of 22,000, then those are the only hotel records you would re-update counts for. Each incremental cycle would be short based on only the newest entries added. For the web, having some pre-aggregate counts, sums, etc is a big time saver where practical.

Expand Join to not limit data

I have a weird question - I understand that Joins return matching data based on the 'ON' stipulation, however the problem I am facing is I need the Business date back for both tables but at the same time i need to join on the date in order to get the totals correct
See below code:
Select
o.Resort,
o.Business_Date,
Occupied,
Comps,
House,
ADR,
Room_Revenue,
Occupied-(Comps+House) AS DandT,
Coalesce(gd.Projected_Occ1,0) AS Projected_Occ1,
Occupied-(Comps+House)+Coalesce(gd.Projected_Occ1,0) as Total
from Occupancy o
left join Group_Details_HF gd
on o.Business_Date = gd.Business_Date
and o.Resort = gd.resort
UNION ALL
select
o.Resort,
o.Business_Date,
Occupied,
Comps,
House,
ADR,
Room_Revenue,
Occupied-(Comps+House) AS DandT,
Coalesce(gd.Projected_Occ1,0) AS Projected_Occ1,
Coalesce(Occupied-(Comps+House),0)+Coalesce(gd.Projected_Occ1,0) as Total
from Occupancy_Forecast o
FULL OUTER JOIN Group_Details_HF gd
on o.Business_Date = gd.Business_Date
and o.Resort = gd.resort
Currently, this gives me the desired results from the Occupancy and Occupancy forecast table however when the business date does not exist in the occupancy forecast table it ignores the group_details table, I need the results to combine the dates when they exist in both or give the unique results for each when there is no match
I have decided to create another pivot table storing the details from Group_Details_HF and then Union together the two tables which has given me the desired result rather than fiddling with the join :)

Join Queries with parameter filter on second query SSMS

I have two tables: EQUIPMENT and WORKORDERS.
EQUIPMENT returns the count of Equipment against a particular depot by the type of Equipment:
MAINTDEPOT EQUIPCOUNT EQUIPTYPE
1 44 MC
2 20 MC
3 5 MC
1 20 FS
2 3 FS
3 10 FS
...and so on. These counts rarely change unless a new bit of kit is put in.
I need to join a count of WORKORDERS to this table, but the work orders have a COSTCENTRE of either A B or E. This is so that I can generate a percentage of equipment with workorders.
I've joined the tables, but when I add a parameter filter to the WORKORDERS COSTCENTRE column the Count of EQUIPMENT changes, and I need it to stay the same.
I'm guessing I need to use subqueries to ensure that the left subquery remains static whilst the filter only changes the right hand one. Does anyone have any idea how I do this?
Here's my current query:
SELECT E.E_MAINTDEPOT, E.E_EQUIPCOUNT, C.Category, E.MYORDER, E.W_WORKCOUNT,
E.E_NOWO, E.W_HRS, E.E_QA, E.E_EGI, E.E_CLASS,
ISNULL(ROUND(CAST(E.E_NOWO AS Float) /
CAST(E.E_EQUIPCOUNT AS Float) * 100, 2), 100) AS RESULT,
SUBSTRING(E.E_CLASS, 1, 1) AS EM_CLASS
FROM (
SELECT T.E_MAINTDEPOT, COUNT(T.EQUIP_NO) AS E_EQUIPCOUNT,
SUM(C.W_WORKCOUNT) AS W_WORKCOUNT,
COUNT(T.EQUIP_NO) - SUM(C.W_WORKCOUNT) AS E_NOWO, T.MYORDER,
T.E_QA, T.E_EGI, T.E_CLASS, SUM(C.W_HRS) AS W_HRS
FROM EQDType AS T
FULL OUTER JOIN EquipWOCount AS C
ON T.EQUIP_NO = C.EQUIP_NO
GROUP BY T.MYORDER, T.E_MAINTDEPOT, T.E_QA, T.E_EGI, T.E_CLASS, C.W_FUNCTION
) AS E
INNER JOIN EQDCategory AS C
ON E.MYORDER = C.Myorder
ORDER BY E.MYORDER, E.E_MAINTDEPOT
Thank you