complex inner join sql - sql

You are my last hope. I've spend all day but I haven't decided how to create this query.
This is my current database diagram
Every storage have 1 roster
Every roster consist from chief and worker. Information about them is on stuff table .
What I try to do? Get all storage(square adress), worker_name, worker_surname, chief_name, chief_surname.
What I have so far
select storage_address,
storage_square,
stuffs.stuff_name as chiefSurname,
stuffs.stuff_surname as chiefName from storages
inner join storageRoster on storageRoster.storageRoster_id=storages.storage_roster_id
inner join Chiefs on storageRoster.chief_id = Chiefs.chief_id
inner join stuffs on Chiefs.chief_stuff_id = stuffs.stuff_id
But in this query I can only get chiefs on every storage. Help please. I am desperate.

You need to join the stuff table twice, once for worker and once for chief:
select storage_address,
storage_square,
cs.stuff_name as chiefSurname,
cs.stuff_surname as chiefName,
ws.stuff_name as workerSurname,
ws.stuff_surname as workerName
from storages
inner join storageRoster on storageRoster.storageRoster_id=storages.storage_roster_id
inner join Chiefs on storageRoster.chief_id = Chiefs.chief_id
inner join stuffs cs on Chiefs.chief_stuff_id = cs.stuff_id
inner join Workers on storageRoster.worker_id = Workers.chief_id
inner join ws cs on Workers.worker_stuff_id = ws.stuff_id

Related

How can I retrieve the other table information?

How can I get the RESULT using SQL?
You can use the Multiple JOINS as follows:
select R.PRJ_NAME, R.SELLER_IDX, CS.COMPANY_NAME, R.BUYER_IDX, CB.COMAPY_NAME
from RECORDS R
join PROJECT Ps on Ps.prj_name = r.seller_idx
join PROJECT Pb on Pb.prj_name = r.buyer_idx
join COMPANY Cs on Cs.company_idx = Ps.company_idx
join COMPANY Cb on Cb.company_idx = Pb.company_idx
I suspect that there are really two tables, projects and companies. If so:
select p.proj_name, p.seller_idx, cs.company_name as seller_name,
p.buyer_idx, cb.company_name as buyer_name
from projects p left join
companies cs
on p.seller_idx = cs.company_idx left join
companies cb
on p.buyer_idx = cb.company_idx;

Problem with the joining of SQL tables via relationships

I am currently having problems trying the run a query for some tables.
Below is what I am trying to do, I just can't seem to get it to work.
I have also duplicated constituent and gifts to show you the relations between soft credit and gifts/constituents
Link to Table Relations Image
SELECT
Constituent.lookup_id,
Constituent.name,
SplitGifts.amount,
SplitGifts.giftaidamount
FROM
dbo.Gifts Gifts
INNER JOIN dbo.Constituent Constituent
ON Constituent.id = Gifts.constituent_id
INNER JOIN dbo.SplitGifts SplitGifts
ON SplitGifts.giftid = Gifts.id
LEFT JOIN dbo.SoftCredit SoftCredit
ON SoftCredit.giftid = Gifts.id
INNER JOIN dbo.Constituent Constituent_1
ON Constituent_1.id = SoftCredit.constituentid
INNER JOIN dbo.Gifts Gifts_1
ON Gifts_1.id = SoftCredit.giftid
INNER JOIN dbo.Package Package
ON Package.id = SplitGifts.packageid
WHERE
Package.lookup_id = N'CORPCHAL'
Basically, I want the
amount and gift_aid_amount from [SplitGifts]
Constituent Name & lookup_id from [constituent] to show up for all Gifts however if a soft credit exists for that gift I need it to get the same fields via the [SoftCredit] table -> Gifts -> SplitGifts -> Fields
You could try if the query below works.
SELECT
Constituent.lookup_id,
Constituent.name,
SplitGifts.amount,
SplitGifts.giftaidamount
FROM
dbo.Gifts Gifts
LEFT JOIN dbo.SoftCredit SoftCredit ON SoftCredit.giftid = Gifts.id
INNER JOIN dbo.Gifts Gifts_1 ON
Gifts_1.id = SoftCredit.giftid OR
(SoftCredit.giftid IS NULL AND Gifts_1.id = Gifts.id)
INNER JOIN dbo.Constituent Constituent ON
Constituent.id = SoftCredit.constituentid OR
(SoftCredit.constituentid IS NULL AND Constituent.id = Gifts_1.constituent_id)
INNER JOIN dbo.SplitGifts SplitGifts ON SplitGifts.giftid = Gifts_1.id
INNER JOIN dbo.Package Package ON Package.id = SplitGifts.packageid
WHERE
Package.lookup_id = N'CORPCHAL'
It joins back to table Gifts (using alias Gifts_1) on the gift reference in SoftCredit or to itself if there is no SoftCredit.
Table Constituent is joined in a similar fashion: it joins on the value of SoftCredit.constituentid and when NULL, it falls back to Gifts_1.constituent_id.
All next joins regarding the gift should refer to Gifts_1 then.
I have not tested it though. But it might give you a hint in a possible solution direction.

how to stop INNER JOIN from showing repeat data

I am working with data on multiple tables and I am trying to get some info but I keep getting repeat data.
SELECT Airport.city, StateInfo.state_name, TravelInfo.destination,
Carrier.unique_carrier_name, CarrierInfo.passengers
FROM Airport
INNER JOIN TravelInfo
ON Airport.airport_id = TravelInfo.destination_airport_id
INNER JOIN Flights
ON Airport.airport_id = Flights.destination_airport_id
INNER JOIN StateInfo
ON Airport.airport_id = StateInfo.airport_id
INNER JOIN Carrier
ON Flights.airline_id = Carrier.airline_id
INNER JOIN CarrierInfo
ON Carrier.airline_id = CarrierInfo.airline_id
WHERE Airport.state = 'CO';
What I am trying to do is get the city name the carrier and a number of passengers but it seems that the output keeps repeating the data.
For example I will get:
As you can see the data gets repeated a few hundred times is there a way to fix this?
You can sum up passangers for city and destination.
SELECT Airport.city, StateInfo.state_name, TravelInfo.destination,
Carrier.unique_carrier_name
,sum( CarrierInfo.passengers) as passengers
FROM Airport
INNER JOIN TravelInfo
ON Airport.airport_id = TravelInfo.destination_airport_id
INNER JOIN Flights
ON Airport.airport_id = Flights.destination_airport_id
INNER JOIN StateInfo
ON Airport.airport_id = StateInfo.airport_id
INNER JOIN Carrier
ON Flights.airline_id = Carrier.airline_id
INNER JOIN CarrierInfo
ON Carrier.airline_id = CarrierInfo.airline_id
WHERE Airport.state = 'CO'
GROUP BY 1,2,3,4;
But I believe this would over report the passenger number because I see duplicate passangers in your output. So somewhere in your joins you are duplicating data.

Left join causing headache

I am troubleshooting a process that is running a very long time, This select statemet runs for over 30 minutes, when i comment out various parts of it, it runs very fast. i have put a * next to the Tables that appear to be causing the issue , the one with two ** has a clustered index on Empid and ChangeDate(these columns are not next to each other) not sure if that matters, also none of these tables has more than 3000 rows. I am hoping there is some simple tweak hat needs to be made. Is there something i should look at in source tables? any suggestions would be appreciated. i have googled 'multiple out joins in single statement' with no luck. For troubleshooting purposes i put the with(nolock) in.
select
je.EmpID,
max(med.ChangeDate) as Max_Medical_ChangeDate,
max(den.ChangeDate) as Max_Dental_ChangeDate,
max(k.ChangeDate) as Max_401K_ChangeDate,
max(ltd.ChangeDate) as Max_LTD_ChangeDate,
max(std.ChangeDate) as Max_STD_ChangeDate,
max(life.ChangeDate) as Max_Life_ChangeDate,
max(sal.ChangeDate) as Max_Salary_ChangeDate,
max(ltdexe.ChangeDate) as Max_LTDEXE_ChangeDate
max(accid.ChangeDate) as Max_Accid_ChangeDate,
max(cancr.ChangeDate) as Max_Cancr_ChangeDate,
max(hosp.ChangeDate) as Max_Hosp_ChangeDate
from Judge_Emp je WITH(NOLOCK)
left join Medical med on je.EmpID = med.EmpID
left join Dental den on med.EmpID = den.EmpID
left join R401K k on den.EmpID = k.EmpID
left join STDIns std on k.EmpID = std.EmpID
left join LTDIns ltd on std.EmpID = ltd.EmpID
* left join LTDEXEIns ltdexe on ltd.EmpID = ltdexe.EmpID
** left join LifeIns life on ltdexe.EmpID = life.EmpID
* left join Salary sal on life.EmpID = sal.EmpID
left join AF_Accid accid on accid.EmpID=sal.EmpID
left join AF_Cancr cancr on cancr.EmpID=accid.EmpID
left join AF_Hosp hosp on hosp.EmpID=cancr.EmpID
group by je.EmpID
Thanks
This is too long for a comment.
If you are using left outer joins, your join conditions should refer to the first table in the chain. For instance:
from Judge_Emp je WITH(NOLOCK)
left join Medical med on je.EmpID = med.EmpID
left join Dental den on je.EmpID = den.EmpID
left join R401K k on je.EmpID = k.EmpID . . .
Rather than:
from Judge_Emp je WITH(NOLOCK)
left join Medical med on je.EmpID = med.EmpID
left join Dental den on med.EmpID = den.EmpID
left join R401K k on den.EmpID = k.EmpID . . .
The reasons is that med.EmptID could be NULL, which would cause the join to fail. (It doesn't make a difference for inner joins).
This probably doesn't affect the performance of the query, though. My guess is that these have multiple matching rows and are generating a Cartesian product for each customer.

How to improve the performance of a SQL query even after adding indexes?

I am trying to execute the following sql query but it takes 22 seconds to execute. the number of returned items is 554192. I need to make this faster and have already put indexes in all the tables involved.
SELECT mc.name AS MediaName,
lcc.name AS Country,
i.overridedate AS Date,
oi.rating,
bl1.firstname + ' ' + bl1.surname AS Byline,
b.id BatchNo,
i.numinbatch ItemNumberInBatch,
bah.changedatutc AS BatchDate,
pri.code AS IssueNo,
pri.name AS Issue,
lm.neptunemessageid AS MessageNo,
lmt.name AS MessageType,
bl2.firstname + ' ' + bl2.surname AS SourceFullName,
lst.name AS SourceTypeDesc
FROM profiles P
INNER JOIN profileresults PR
ON P.id = PR.profileid
INNER JOIN items i
ON PR.itemid = I.id
INNER JOIN batches b
ON b.id = i.batchid
INNER JOIN itemorganisations oi
ON i.id = oi.itemid
INNER JOIN lookup_mediachannels mc
ON i.mediachannelid = mc.id
LEFT OUTER JOIN lookup_cities lc
ON lc.id = mc.cityid
LEFT OUTER JOIN lookup_countries lcc
ON lcc.id = mc.countryid
LEFT OUTER JOIN itembylines ib
ON ib.itemid = i.id
LEFT OUTER JOIN bylines bl1
ON bl1.id = ib.bylineid
LEFT OUTER JOIN batchactionhistory bah
ON b.id = bah.batchid
INNER JOIN itemorganisationissues ioi
ON ioi.itemorganisationid = oi.id
INNER JOIN projectissues pri
ON pri.id = ioi.issueid
LEFT OUTER JOIN itemorganisationmessages iom
ON iom.itemorganisationid = oi.id
LEFT OUTER JOIN lookup_messages lm
ON iom.messageid = lm.id
LEFT OUTER JOIN lookup_messagetypes lmt
ON lmt.id = lm.messagetypeid
LEFT OUTER JOIN itemorganisationsources ios
ON ios.itemorganisationid = oi.id
LEFT OUTER JOIN bylines bl2
ON bl2.id = ios.bylineid
LEFT OUTER JOIN lookup_sourcetypes lst
ON lst.id = ios.sourcetypeid
WHERE p.id = #profileID
AND b.statusid IN ( 6, 7 )
AND bah.batchactionid = 6
AND i.statusid = 2
AND i.isrelevant = 1
when looking at the execution plan I can see an step which is costing 42%. Is there any way I could get this to a lower threshold or any way that I can improve the performance of the whole query.
Remove the profiles table as it is not needed and change the WHERE clause to
WHERE PR.profileid = #profileID
You have a left outer join on the batchactionhistory table but also have a condition in your WHERE clause which turns it back into an inner join. Change you code to this:
LEFT OUTER JOIN batchactionhistory bah
ON b.id = bah.batchid
AND bah.batchactionid = 6
You don't need the batches table as it is used to join other tables which could be joined directly and to show the id in you SELECT which is also available in other tables. Make the following changes:
i.batchidid AS BatchNo,
LEFT OUTER JOIN batchactionhistory bah
ON i.batchidid = bah.batchid
Are any of the fields that are used in joins or the WHERE clause from tables that contain large amounts of data but are not indexed. If so try adding an index on at time to the largest table.
Do you need every field in the result - if you could loose one or to you maybe could reduce the number of tables further.
First, if this is not a stored procedure, make it one. That's a lot of text for sql server to complile.
Next, my experience is that "worst practices" are occasionally a good idea. Specifically, I have been able to improve performance by splitting large queries into a couple or three small ones and assembling the results.
If this query is associated with a .net, coldfusion, java, etc application, you might be able to do the split/re-assemble in your application code. If not, a temporary table might come in handy.