SQL Inner Join Combining Rows in Results - Too Few Results - sql

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?

Related

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 :)

Access 2013 SQL, three tables, two using sum wrong results

Can someone please help me with this issue? I've scoured the Internet looking at dozens of examples, but i just can't find a solution that works.
I am using Access 2013. The problem is that I am trying to make a query that will highlight all part numbers from a supplier that either has customer back orders and/or overdue deliveries.
I am using three tables:
tbl_Inventory_Master which I require the part number, on hand stock value, and the supplier code.
For any back orders I need to join the tbl_Customer_Back_Order table as I need the count of back order lines and the sum of the back order quantity.
If the supplier has a late delivery, then I need to add the tbl_On_Order table showing the count of overdue deliveries and the sum of the overdue quantities.
The query is retrieving the data but the returned quantities are double what they should be.
SELECT
I.Inventory_Part_Num, I.Description, I.On_Hand_Stock,
COUNT (B.Part_Number) AS Back_Order_Count, SUM(B.Back_Order_Qty) as BO_Qty,
COUNT(O.Part_Number) AS Late_Deliveries_Count, SUM(O.Order_Qty) AS Late_Qty
FROM (tbl_Inventory_Master AS I
LEFT OUTER JOIN tbl_Customer_Back_Order AS B
ON I.Inventory_Part_Num = B.Part_Number)
LEFT OUTER tbl_On_Order AS O
ON I.Inventory_Part_Num = O.Part_Number
WHERE
I.Customer_Code = '274' AND
O.Due_Date < [ENTER TODAYS DATE IN FORMAT DD/MM/YYYY]
GROUP BY I.Inventory_Part_Num, I.Description, I.On_Hand_Stock
For example, for the part number 2022940 I should have 10 back order lines and an overdue quantity of 43. Instead, the query is returning 20 back order lines and an overdue quantity sum of 86.
From the on order table I have three orders totaling 144 pieces, instead the query is returning 960.
Can someone please advise, as this is driving me crazy?
You are joining along unrelated dimensions, so you need to aggregate before joining:
SELECT I.Inventory_Part_Num, I.Description, I.On_Hand_Stock,
B.Back_Order_Count, B.BO_Qty,
O.Late_Deliveries_Count, O.Late_Qty
FROM (tbl_Inventory_Master AS I LEFT OUTER JOIN
(SELECT B.Part_Number, COUNT(*) as Back_Order_Count,
SUM(B.Back_Order_Qty) as BO_Qty
FROM tbl_Customer_Back_Order AS B
GROUP BY B.Part_Number
) as B
ON I.Inventory_Part_Num = B.Part_Number
) LEFT JOIN
(SELECT O.Part_Number, COUNT(O.Part_Number) AS Late_Deliveries_Count,
SUM(O.Order_Qty) AS Late_Qty
FROM tbl_On_Order AS O
WHERE O.Due_Date < [ENTER TODAYS DATE IN FORMAT DD/MM/YYYY]
GROUP BY O.Part_Number
) as O
ON I.Inventory_Part_Num = O.Part_Number
WHERE I.Customer_Code = '274';
Notice the outer aggregation is no longer needed.

Joining a selected table to a cross joined table

I have a table, flight_schedule, that consists of a bunch of flight segments. Below I have a Terradata SQL query that creates a list of two segment itineraries between Chicago and Denver. i.e. each row has two flights that eventually get the passenger from Chicago to Denver. For example, the first row contains flight information on a leg from Chicago to Omaha and then a later leg from Omaha to Denver. This query works just fine.
SELECT A.flt_num, A.dprt_sta_cd, A.arrv_sta_cd, A.sch_dprt_dtml, A.sch_arrv_dtml,
B.flt_num, B.dprt_sta_cd, B.arrv_sta_cd, B.sch_dprt_dtml, B.sch_arrv_dtml
FROM
flight_schedule A
CROSS JOIN
flight_schedule B
WHERE
A.dprt_sta_cd = 'Chicago' AND
B.arrv_sta_cd = 'Denver' AND
A.arrv_sta_cd = B.dprt_sta_cd AND
A.sch_arrv_dtml < B.sch_dprt_dtml
ORDER BY B.sch_arrv_dtml;
I have another table, flight_seat_inventory, that consists of seats available in different cabins for each flight number. The query below aggregates total available seats for each flight number. This query is also A-OK.
SELECT flt_num, SUM(seat_cnt) as avail_seats
FROM flight_seat_inventory
GROUP BY flt_num;
I want to combine these two queries with a LEFT JOIN, twice, so that each flight has a corresponding avail_seats value. How can I do this?
For added clarity, I think my desired Select statement looks like this:
SELECT A.flt_num, A.dprt_sta_cd, A.arrv_sta_cd, A.sch_dprt_dtml, A.sch_arrv_dtml, C.avail_seats
B.flt_num, B.dprt_sta_cd, B.arrv_sta_cd, B.sch_dprt_dtml, B.sch_arrv_dtml, D.avail_seats
flight_schedule is HUGE, so I suspect it's more efficient to do the LEFT JOIN after the CROSS JOIN. Again, using Teradata SQL.
Thanks!
I needed to declare the second seats query as a temporary table using a WITH command before I did the LEFT JOIN:
WITH tempSeatsTable AS (
SELECT flt_num, SUM(seat_cnt) as avail_seats
FROM flight_seat_inventory
GROUP BY flt_num
)
SELECT
A.flt_num, A.dprt_sta_cd, A.arrv_sta_cd, A.sch_dprt_dtml, A.sch_arrv_dtml, C.avail_seats
B.flt_num, B.dprt_sta_cd, B.arrv_sta_cd, B.sch_dprt_dtml, B.sch_arrv_dtml, D.avail_seats
FROM
flight_schedule A
CROSS JOIN
flight_schedule B
LEFT JOIN
tempSeatsTable C
ON A.flt_num = C.flt_num
LEFT JOIN
tempSeatsTable D
ON B.flt_num = D.flt_num
WHERE
A.dprt_sta_cd = 'Chicago' AND
B.arrv_sta_cd = 'Denver' AND
A.arrv_sta_cd = B.dprt_sta_cd AND
A.sch_arrv_dtml < B.sch_dprt_dtml
ORDER BY B.sch_arrv_dtml;

Several inner joins producing too many rows

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).

MySQL joins with WHERE clause

I have 2 queries which display 2 different values but the results from one query are unexpected.
Query1:
SELECT SUM(T.amount_reward_user) AS total_grouping
FROM fem_user_cards UC
LEFT JOIN fem_transactions T USING(card_number)
LEFT JOIN fem_company_login FCL
ON T.fem_company_login_id=FCL.fem_company_login_id
WHERE UC.fem_user_login_id=193
AND FCL.grouping<>0 AND T.from_group=1 AND T.authorised=1
GROUP BY UC.fem_user_login_id
The above query gives me the total reward amount for the user 193. Here the condition is the reward amount which i am getting out of this query must be from the group which is evident from T.from_group=1. So this seems to be working correct.
Query2:
SELECT SUM(T.amount_reward_user) AS total_grouping
FROM fem_transactions T
LEFT JOIN fem_company_login FCL
ON T.fem_company_login_id=FCL.fem_company_login_id
WHERE T.fem_user_login_id=193
AND FCL.grouping<>0 AND T.from_group=1 AND T.authorised=1
In this query even though T.from_group=1 it is adding up the reward amount from T.from_group=0 as well. Does anyone know what the problem is?
For example:
The user 193 purchased something in a company A(in the group so T.from_group=1) for $5 and got the reward of $1 and bought another product for $5 from company B(out of group so T.from_group=0) and get a reward of $1 again.
My expected output is: 1
I am getting:
Query1: 1
Query2: 2
I could simply use the query 1 but i have issues with other things when i use that so i need to understand what is going on really!!
My aim is to get the sum of reward amounts from the database. The sum should be of different grouped companies. That is if we have 5 different grouped companies and user is using his moneycard in those 5 companies, I should get 5 different totals. If he used his card in any company which is not in the group the total should not include transaction from this un-grouped company. I have C++ code to feed the database as transactions happens. My fem_transactions table has company_id, amount_reward_user, fem_user_login_id, from_group (this decides if the user has transacted out of the group or from the group), authorized etc..
I want to filter the amount spent by the user 193 in each group separately.
I understood the JOINTS concepts now but i need to know why t.from_group on the second query is ignored ?
The problem is that you have criteria in the Where clause against columns on the right side of the Left Join. In the both queries, this is And FCL.grouping <> 0. This effectively changes the Left Join to an Inner Join since you are in requiring that an FCL.grouping value exist and not be zero (or Null). What you want, I think, is to move that criteria into the On clause:
First query:
Select Sum(T.amount_reward_user) AS total_grouping
From fem_user_cards UC
Left Join fem_transactions T Using(card_number)
Left Join fem_company_login FCL
On FCL.fem_company_login_id = T.fem_company_login_id
And FCL.grouping<>0
Where UC.fem_user_login_id=193
And T.from_group=1
And T.authorised=1
Group By UC.fem_user_login_id
Second query
Select Sum(T.amount_reward_user) AS total_grouping
From fem_transactions T
Left Join fem_company_login FCL
On FCL.fem_company_login_id = T.fem_company_login_id
And FCL.grouping<>0
Where UC.fem_user_login_id=193
And T.from_group=1
And T.authorised=1
What is not clear in all of this is what you are trying to achieve. I.e., why even have the Left Joins in either query if you are not filtering on them. If you do specifically want to filter for rows where there is a fem_company_login value with a grouping value <> 0, then use your original query and change the Left Join to an Inner Join. If you want to filter for people that either have a grouping value <> 0 or no value at all then do something like:
Select Sum(T.amount_reward_user) AS total_grouping
From fem_transactions T
Left Join fem_company_login FCL
On FCL.fem_company_login_id = T.fem_company_login_id
Where UC.fem_user_login_id=193
And T.from_group=1
And T.authorised=1
And ( FCL.PrimaryKeyColumn Is Null Or FCL.grouping <> 0 )